blob: 6c27bc61e432c52b7cc0e6cf3feff7736abd0929 [file] [log] [blame]
Elliott Hughesa2501992011-08-26 19:39:54 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "check_jni.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070018
Andreas Gampeef4afe92015-07-27 21:03:25 -070019#include <iomanip>
Elliott Hughesa2501992011-08-26 19:39:54 -070020#include <sys/mman.h>
21#include <zlib.h>
22
Mathieu Chartierc7853442015-03-27 14:35:38 -070023#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070024#include "art_method-inl.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080025#include "base/logging.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070026#include "base/to_str.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070027#include "class_linker.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080028#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070029#include "dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070030#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070031#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080032#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080033#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034#include "mirror/object-inl.h"
35#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070036#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080037#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070038#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070039#include "scoped_thread_state_change-inl.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070040#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070041#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070042
43namespace art {
44
Elliott Hughesa2501992011-08-26 19:39:54 -070045/*
46 * ===========================================================================
47 * JNI function helpers
48 * ===========================================================================
49 */
50
Elliott Hughes3f6635a2012-06-19 13:37:49 -070051// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -070052#define kFlag_Default 0x0000
53
Elliott Hughes3f6635a2012-06-19 13:37:49 -070054#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
55#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
56#define kFlag_CritGet 0x0002 // This is a critical "get".
57#define kFlag_CritRelease 0x0003 // This is a critical "release".
58#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
Elliott Hughesa2501992011-08-26 19:39:54 -070059
Elliott Hughes3f6635a2012-06-19 13:37:49 -070060#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
61#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -070062
Elliott Hughes3f6635a2012-06-19 13:37:49 -070063#define kFlag_Release 0x0010 // Are we in a non-critical release function?
64#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -070065
Elliott Hughes3f6635a2012-06-19 13:37:49 -070066#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -070067
Elliott Hughes485cac42011-12-09 17:49:35 -080068#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
Alex Light48ffe062015-08-19 15:23:23 -070069
70class VarArgs;
Ian Rogers68d8b422014-07-17 11:09:10 -070071/*
72 * Java primitive types:
73 * B - jbyte
74 * C - jchar
75 * D - jdouble
76 * F - jfloat
77 * I - jint
78 * J - jlong
79 * S - jshort
80 * Z - jboolean (shown as true and false)
81 * V - void
82 *
83 * Java reference types:
84 * L - jobject
85 * a - jarray
86 * c - jclass
87 * s - jstring
88 * t - jthrowable
89 *
90 * JNI types:
91 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
92 * f - jfieldID
93 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
94 * m - jmethodID
95 * p - void*
96 * r - jint (for release mode arguments)
97 * u - const char* (Modified UTF-8)
98 * z - jsize (for lengths; use i if negative values are okay)
99 * v - JavaVM*
100 * w - jobjectRefType
101 * E - JNIEnv*
102 * . - no argument; just print "..." (used for varargs JNI calls)
103 *
104 */
105union JniValueType {
106 jarray a;
107 jboolean b;
108 jclass c;
109 jfieldID f;
110 jint i;
111 jmethodID m;
112 const void* p; // Pointer.
113 jint r; // Release mode.
114 jstring s;
115 jthrowable t;
116 const char* u; // Modified UTF-8.
117 JavaVM* v;
118 jobjectRefType w;
119 jsize z;
120 jbyte B;
121 jchar C;
122 jdouble D;
123 JNIEnv* E;
124 jfloat F;
125 jint I;
126 jlong J;
127 jobject L;
128 jshort S;
129 const void* V; // void
130 jboolean Z;
Alex Light48ffe062015-08-19 15:23:23 -0700131 const VarArgs* va;
132};
133
134/*
135 * A structure containing all the information needed to validate varargs arguments.
136 *
137 * Note that actually getting the arguments from this structure mutates it so should only be done on
138 * owned copies.
139 */
140class VarArgs {
141 public:
142 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
143 va_copy(vargs_, var);
144 }
145
146 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
147
148 ~VarArgs() {
149 if (type_ == kTypeVaList) {
150 va_end(vargs_);
151 }
152 }
153
154 VarArgs(VarArgs&& other) {
155 m_ = other.m_;
156 cnt_ = other.cnt_;
157 type_ = other.type_;
158 if (other.type_ == kTypeVaList) {
159 va_copy(vargs_, other.vargs_);
160 } else {
161 ptr_ = other.ptr_;
162 }
163 }
164
165 // This method is const because we need to ensure that one only uses the GetValue method on an
166 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
167 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
168 // we want to use one we need to Clone() it.
169 VarArgs Clone() const {
170 if (type_ == kTypeVaList) {
171 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
172 // messed up if the source argument is not the exact type 'va_list'.
173 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
174 } else {
175 return VarArgs(m_, cnt_, ptr_);
176 }
177 }
178
179 jmethodID GetMethodID() const {
180 return m_;
181 }
182
183 JniValueType GetValue(char fmt) {
184 JniValueType o;
185 if (type_ == kTypeVaList) {
186 switch (fmt) {
187 case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
188 case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
189 case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
190 case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
191 case 'I': o.I = va_arg(vargs_, jint); break;
192 case 'J': o.J = va_arg(vargs_, jlong); break;
193 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
194 case 'D': o.D = va_arg(vargs_, jdouble); break;
195 case 'L': o.L = va_arg(vargs_, jobject); break;
196 default:
197 LOG(FATAL) << "Illegal type format char " << fmt;
198 UNREACHABLE();
199 }
200 } else {
201 CHECK(type_ == kTypePtr);
202 jvalue v = ptr_[cnt_];
203 cnt_++;
204 switch (fmt) {
205 case 'Z': o.Z = v.z; break;
206 case 'B': o.B = v.b; break;
207 case 'C': o.C = v.c; break;
208 case 'S': o.S = v.s; break;
209 case 'I': o.I = v.i; break;
210 case 'J': o.J = v.j; break;
211 case 'F': o.F = v.f; break;
212 case 'D': o.D = v.d; break;
213 case 'L': o.L = v.l; break;
214 default:
215 LOG(FATAL) << "Illegal type format char " << fmt;
216 UNREACHABLE();
217 }
218 }
219 return o;
220 }
221
222 private:
223 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
224 va_copy(vargs_, var);
225 }
226
227 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
228
229 enum VarArgsType {
230 kTypeVaList,
231 kTypePtr,
232 };
233
234 jmethodID m_;
235 VarArgsType type_;
236 uint32_t cnt_;
237 union {
238 va_list vargs_;
239 const jvalue* ptr_;
240 };
Elliott Hughesa0957642011-09-02 14:27:33 -0700241};
242
Elliott Hughesa2501992011-08-26 19:39:54 -0700243class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800244 public:
Roland Levillain3887c462015-08-12 18:15:42 +0100245 ScopedCheck(int flags, const char* functionName, bool has_method = true)
Ian Rogers68d8b422014-07-17 11:09:10 -0700246 : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700247 }
248
Ian Rogers68d8b422014-07-17 11:09:10 -0700249 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700250
Elliott Hughes81ff3182012-03-23 20:35:56 -0700251 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
252 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
253 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
254 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700255 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700256 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700257 AbortF("illegal class name '%s'\n"
258 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
259 class_name);
260 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700261 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700262 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700263 }
264
265 /*
266 * Verify that this instance field ID is valid for this object.
267 *
268 * Assumes "jobj" has already been validated.
269 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700270 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700271 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700272 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700273 if (o == nullptr) {
274 AbortF("field operation on NULL object: %p", java_object);
275 return false;
276 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700277 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700278 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700279 AbortF("field operation on invalid %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700280 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700281 java_object);
282 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700283 }
284
Andreas Gampe08883de2016-11-08 13:20:52 -0800285 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800286 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700287 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700288 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800289 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700290 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700291 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700292 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700293 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700294 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700295 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700296 }
297
298 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700299 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700300 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700301 bool CheckNonNull(const void* ptr) {
302 if (UNLIKELY(ptr == nullptr)) {
303 AbortF("non-nullable argument was NULL");
304 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700305 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700306 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700307 }
308
309 /*
310 * Verify that the method's return type matches the type of call.
311 * 'expectedType' will be "L" for all objects, including arrays.
312 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700313 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
314 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700315 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800316 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800317 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700318 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700319 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700320 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700321 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700322 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700323 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700324 bool is_static = (invoke == kStatic);
325 if (is_static != m->IsStatic()) {
326 if (is_static) {
327 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700328 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700329 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700330 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700331 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700332 }
333 return false;
334 }
335 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700336 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700337 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700338 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700339 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700340 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700341 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700342 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700343 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700344 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700345 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700346 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700347 return false;
348 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700349 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
350 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700351 return false;
352 }
353 }
354 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700355 }
356
357 /*
358 * Verify that this static field ID is valid for this class.
359 *
360 * Assumes "java_class" has already been validated.
361 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700362 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700363 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700364 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Andreas Gampe08883de2016-11-08 13:20:52 -0800365 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800366 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700367 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700368 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700369 if (c != f->GetDeclaringClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700370 AbortF("static jfieldID %p not valid for class %s", fid,
371 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700372 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700373 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700374 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700375 }
376
377 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700378 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700379 *
380 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700381 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700382 * allow bad code in the system though.
383 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700384 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700385 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700386 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700387 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800388 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800389 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700390 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700391 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700392 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700393 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700394 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
395 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700396 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700397 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700398 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700399 }
400
401 /*
402 * Verify that "mid" is appropriate for "jobj".
403 *
404 * Make sure the object is an instance of the method's declaring class.
405 * (Note the mid might point to a declaration in an interface; this
406 * will be handled automatically by the instanceof check.)
407 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700408 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700409 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800410 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800411 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700412 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700413 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700414 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700415 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700416 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700417 return false;
418 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700419 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
420 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700421 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700422 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700423 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700424 }
425
426 /**
427 * The format string is a sequence of the following characters,
428 * and must be followed by arguments of the corresponding types
429 * in the same order.
430 *
431 * Java primitive types:
432 * B - jbyte
433 * C - jchar
434 * D - jdouble
435 * F - jfloat
436 * I - jint
437 * J - jlong
438 * S - jshort
439 * Z - jboolean (shown as true and false)
440 * V - void
441 *
442 * Java reference types:
443 * L - jobject
444 * a - jarray
445 * c - jclass
446 * s - jstring
447 *
448 * JNI types:
449 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
450 * f - jfieldID
451 * m - jmethodID
452 * p - void*
453 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700454 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700455 * z - jsize (for lengths; use i if negative values are okay)
456 * v - JavaVM*
457 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700458 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700459 *
460 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
461 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700462 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700463 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700464 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700465 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700466 // We need to guard some of the invocation interface's calls: a bad caller might
467 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700468 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800469 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
470 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700471 }
472 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700473
Ian Rogersef7d42f2014-01-06 12:55:46 -0800474 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700475 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700476 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700477 for (size_t i = 0; fmt[i] != '\0'; ++i) {
478 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
479 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700480 StringAppendF(&msg, ", ");
481 }
482 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700483
Elliott Hughes485cac42011-12-09 17:49:35 -0800484 if ((flags_ & kFlag_ForceTrace) != 0) {
485 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
486 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700487 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700488 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700489 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
490 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700491 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700492 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
493 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700494 }
495 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700496 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700497 }
498 }
499
500 // We always do the thorough checks on entry, and never on exit...
501 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700502 for (size_t i = 0; fmt[i] != '\0'; ++i) {
503 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
504 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700505 }
506 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700507 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700508 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700509 }
510
Ian Rogers68d8b422014-07-17 11:09:10 -0700511 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
512 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800513 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700514 // We need to guard some of the invocation interface's calls: a bad caller might
515 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
516 Thread* self = Thread::Current();
517 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
518 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700519 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700520 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
521 }
522 }
523 if (should_trace) {
524 std::string msg;
525 for (size_t i = 0; fmt[i] != '\0'; ++i) {
526 TraceNonHeapValue(fmt[i], args[i], &msg);
527 if (fmt[i + 1] != '\0') {
528 StringAppendF(&msg, ", ");
529 }
530 }
531
532 if ((flags_ & kFlag_ForceTrace) != 0) {
533 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
534 } else if (entry) {
535 if (has_method_) {
536 Thread* self = Thread::Current();
537 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700538 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700539 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700540 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
541 indent_ = methodName.size() + 1;
542 } else {
543 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
544 indent_ = 0;
545 }
546 } else {
547 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
548 }
549 }
550
551 // We always do the thorough checks on entry, and never on exit...
552 if (entry) {
553 for (size_t i = 0; fmt[i] != '\0'; ++i) {
554 if (!CheckNonHeapValue(fmt[i], args[i])) {
555 return false;
556 }
557 }
558 }
559 return true;
560 }
561
562 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700563 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700564 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700565 if (method == nullptr) {
566 AbortF("expected non-null method");
567 return false;
568 }
569 mirror::Class* c = method->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700570 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
571 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700572 AbortF("expected java.lang.reflect.Method or "
573 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700574 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700575 return false;
576 }
577 return true;
578 }
579
Andreas Gampe13b27842016-11-07 16:48:23 -0800580 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
581 ArtMethod* method = jni::DecodeArtMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700582 if (method == nullptr) {
583 AbortF("expected non-null constructor");
584 return false;
585 }
586 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700587 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700588 return false;
589 }
590 return true;
591 }
592
593 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700594 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700595 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700596 if (field == nullptr) {
597 AbortF("expected non-null java.lang.reflect.Field");
598 return false;
599 }
600 mirror::Class* c = field->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700601 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700602 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700603 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700604 return false;
605 }
606 return true;
607 }
608
609 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700610 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700611 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700612 if (!obj->GetClass()->IsThrowableClass()) {
613 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700614 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700615 return false;
616 }
617 return true;
618 }
619
620 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700621 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700622 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700623 if (!c->IsThrowableClass()) {
624 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700625 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700626 return false;
627 }
628 return true;
629 }
630
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700631 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700632 IndirectRefKind found_kind;
633 if (expected_kind == kLocal) {
Andreas Gampedc061d02016-10-24 13:19:37 -0700634 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700635 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
636 found_kind = kLocal;
637 }
638 } else {
Andreas Gampedc061d02016-10-24 13:19:37 -0700639 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700640 }
641 if (obj != nullptr && found_kind != expected_kind) {
642 AbortF("expected reference of kind %s but found %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700643 GetIndirectRefKindString(expected_kind),
644 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700645 obj);
646 return false;
647 }
648 return true;
649 }
650
651 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700652 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700653 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700654 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700655 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700656 return false;
657 }
658 return true;
659 }
660
661 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700662 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700663 if (!CheckArray(soa, array)) {
664 return false;
665 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700666 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700667 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
668 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700669 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700670 return false;
671 }
672 return true;
673 }
674
675 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
676 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700677 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700678 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
679 return false;
680 }
681 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
682 return false;
683 }
Andreas Gampe08883de2016-11-08 13:20:52 -0800684 ArtField* field = jni::DecodeArtField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700685 DCHECK(field != nullptr); // Already checked by Check.
686 if (is_static != field->IsStatic()) {
687 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700688 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700689 return false;
690 }
691 if (type != field->GetTypeAsPrimitiveType()) {
692 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700693 field->PrettyField().c_str(),
694 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700695 PrettyDescriptor(type).c_str(), fid);
696 return false;
697 }
698 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700699 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700700 if (o == nullptr || !o->IsClass()) {
701 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700702 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700703 return false;
704 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700705 ObjPtr<mirror::Class> c = o->AsClass();
706 if (c != field->GetDeclaringClass()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700707 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700708 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700709 return false;
710 }
711 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700712 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700713 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
714 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700715 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700716 return false;
717 }
718 }
719 return true;
720 }
721
722 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800723 enum InstanceKind {
724 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700725 kDirectByteBuffer,
726 kObject,
727 kString,
728 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800729 };
730
731 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700732 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800733 * an instance of expectedClass.
734 *
735 * Because we're looking at an object on the GC heap, we have to switch
736 * to "running" mode before doing the checks.
737 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700738 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700739 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800740 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800741 switch (kind) {
742 case kClass:
743 what = "jclass";
744 break;
745 case kDirectByteBuffer:
746 what = "direct ByteBuffer";
747 break;
748 case kObject:
749 what = "jobject";
750 break;
751 case kString:
752 what = "jstring";
753 break;
754 case kThrowable:
755 what = "jthrowable";
756 break;
757 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700758 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800759 }
760
Ian Rogersef7d42f2014-01-06 12:55:46 -0800761 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700762 if (null_ok) {
763 return true;
764 } else {
765 AbortF("%s received NULL %s", function_name_, what);
766 return false;
767 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800768 }
769
Mathieu Chartier0795f232016-09-27 18:43:30 -0700770 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700771 if (obj == nullptr) {
772 // Either java_object is invalid or is a cleared weak.
773 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
774 bool okay;
Andreas Gampedc061d02016-10-24 13:19:37 -0700775 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700776 okay = false;
777 } else {
778 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700779 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700780 }
781 if (!okay) {
782 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700783 what,
784 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
785 java_object,
786 obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700787 return false;
788 }
789 }
790
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700791 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700792 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700793 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700794 what,
795 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
796 java_object,
797 obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800798 return false;
799 }
800
801 bool okay = true;
802 switch (kind) {
803 case kClass:
804 okay = obj->IsClass();
805 break;
806 case kDirectByteBuffer:
807 UNIMPLEMENTED(FATAL);
808 break;
809 case kString:
810 okay = obj->GetClass()->IsStringClass();
811 break;
812 case kThrowable:
813 okay = obj->GetClass()->IsThrowableClass();
814 break;
815 case kObject:
816 break;
817 }
818 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700819 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800820 return false;
821 }
822
823 return true;
824 }
825
Ian Rogers68d8b422014-07-17 11:09:10 -0700826 /*
827 * Verify that the "mode" argument passed to a primitive array Release
828 * function is one of the valid values.
829 */
830 bool CheckReleaseMode(jint mode) {
831 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
832 AbortF("unknown value for release mode: %d", mode);
833 return false;
834 }
835 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700836 }
837
Ian Rogers68d8b422014-07-17 11:09:10 -0700838 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700839 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700840 switch (fmt) {
841 case 'a': // jarray
842 return CheckArray(soa, arg.a);
843 case 'c': // jclass
844 return CheckInstance(soa, kClass, arg.c, false);
845 case 'f': // jfieldID
Andreas Gampe08883de2016-11-08 13:20:52 -0800846 return CheckFieldID(arg.f) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700847 case 'm': // jmethodID
Andreas Gampe13b27842016-11-07 16:48:23 -0800848 return CheckMethodID(arg.m) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700849 case 'r': // release int
850 return CheckReleaseMode(arg.r);
851 case 's': // jstring
852 return CheckInstance(soa, kString, arg.s, false);
853 case 't': // jthrowable
854 return CheckInstance(soa, kThrowable, arg.t, false);
855 case 'E': // JNIEnv*
856 return CheckThread(arg.E);
857 case 'L': // jobject
858 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700859 case '.': // A VarArgs list
860 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700861 default:
862 return CheckNonHeapValue(fmt, arg);
863 }
864 }
865
Alex Light48ffe062015-08-19 15:23:23 -0700866 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700867 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700868 CHECK(args_p != nullptr);
869 VarArgs args(args_p->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800870 ArtMethod* m = CheckMethodID(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700871 if (m == nullptr) {
872 return false;
873 }
874 uint32_t len = 0;
875 const char* shorty = m->GetShorty(&len);
876 // Skip the return type
877 CHECK_GE(len, 1u);
878 len--;
879 shorty++;
880 for (uint32_t i = 0; i < len; i++) {
881 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
882 return false;
883 }
884 }
885 return true;
886 }
887
Ian Rogers68d8b422014-07-17 11:09:10 -0700888 bool CheckNonHeapValue(char fmt, JniValueType arg) {
889 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700890 case 'p': // TODO: pointer - null or readable?
891 case 'v': // JavaVM*
892 case 'B': // jbyte
893 case 'C': // jchar
894 case 'D': // jdouble
895 case 'F': // jfloat
896 case 'I': // jint
897 case 'J': // jlong
898 case 'S': // jshort
899 break; // Ignored.
900 case 'b': // jboolean, why two? Fall-through.
901 case 'Z':
902 return CheckBoolean(arg.Z);
903 case 'u': // utf8
904 if ((flags_ & kFlag_Release) != 0) {
905 return CheckNonNull(arg.u);
906 } else {
907 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
908 return CheckUtfString(arg.u, nullable);
909 }
910 case 'w': // jobjectRefType
911 switch (arg.w) {
912 case JNIInvalidRefType:
913 case JNILocalRefType:
914 case JNIGlobalRefType:
915 case JNIWeakGlobalRefType:
916 break;
917 default:
918 AbortF("Unknown reference type");
919 return false;
920 }
921 break;
922 case 'z': // jsize
923 return CheckLengthPositive(arg.z);
924 default:
925 AbortF("unknown format specifier: '%c'", fmt);
926 return false;
927 }
928 return true;
929 }
930
931 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
932 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700933 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700934 switch (fmt) {
935 case 'L': // jobject fall-through.
936 case 'a': // jarray fall-through.
937 case 's': // jstring fall-through.
938 case 't': // jthrowable fall-through.
939 if (arg.L == nullptr) {
940 *msg += "NULL";
941 } else {
942 StringAppendF(msg, "%p", arg.L);
943 }
944 break;
945 case 'c': { // jclass
946 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -0700947 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700948 if (c == nullptr) {
949 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700950 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700951 StringAppendF(msg, "INVALID POINTER:%p", jc);
952 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700953 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -0700954 } else {
David Sehr709b0702016-10-13 09:12:37 -0700955 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -0700956 if (!entry) {
957 StringAppendF(msg, " (%p)", jc);
958 }
959 }
960 break;
961 }
962 case 'f': { // jfieldID
963 jfieldID fid = arg.f;
Andreas Gampe08883de2016-11-08 13:20:52 -0800964 ArtField* f = jni::DecodeArtField(fid);
David Sehr709b0702016-10-13 09:12:37 -0700965 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -0700966 if (!entry) {
967 StringAppendF(msg, " (%p)", fid);
968 }
969 break;
970 }
971 case 'm': { // jmethodID
972 jmethodID mid = arg.m;
Andreas Gampe13b27842016-11-07 16:48:23 -0800973 ArtMethod* m = jni::DecodeArtMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -0700974 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -0700975 if (!entry) {
976 StringAppendF(msg, " (%p)", mid);
977 }
978 break;
979 }
Alex Light48ffe062015-08-19 15:23:23 -0700980 case '.': {
981 const VarArgs* va = arg.va;
982 VarArgs args(va->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800983 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700984 uint32_t len;
985 const char* shorty = m->GetShorty(&len);
986 CHECK_GE(len, 1u);
987 // Skip past return value.
988 len--;
989 shorty++;
990 // Remove the previous ', ' from the message.
991 msg->erase(msg->length() - 2);
992 for (uint32_t i = 0; i < len; i++) {
993 *msg += ", ";
994 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
995 }
996 break;
997 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700998 default:
999 TraceNonHeapValue(fmt, arg, msg);
1000 break;
1001 }
1002 }
1003
1004 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1005 switch (fmt) {
1006 case 'B': // jbyte
1007 if (arg.B >= 0 && arg.B < 10) {
1008 StringAppendF(msg, "%d", arg.B);
1009 } else {
1010 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1011 }
1012 break;
1013 case 'C': // jchar
1014 if (arg.C < 0x7f && arg.C >= ' ') {
1015 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1016 } else {
1017 StringAppendF(msg, "U+%x", arg.C);
1018 }
1019 break;
1020 case 'F': // jfloat
1021 StringAppendF(msg, "%g", arg.F);
1022 break;
1023 case 'D': // jdouble
1024 StringAppendF(msg, "%g", arg.D);
1025 break;
1026 case 'S': // jshort
1027 StringAppendF(msg, "%d", arg.S);
1028 break;
1029 case 'i': // jint - fall-through.
1030 case 'I': // jint
1031 StringAppendF(msg, "%d", arg.I);
1032 break;
1033 case 'J': // jlong
1034 StringAppendF(msg, "%" PRId64, arg.J);
1035 break;
1036 case 'Z': // jboolean
1037 case 'b': // jboolean (JNI-style)
1038 *msg += arg.b == JNI_TRUE ? "true" : "false";
1039 break;
1040 case 'V': // void
1041 DCHECK(arg.V == nullptr);
1042 *msg += "void";
1043 break;
1044 case 'v': // JavaVM*
1045 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1046 break;
1047 case 'E':
1048 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1049 break;
1050 case 'z': // non-negative jsize
1051 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1052 // We only treat this specially so we can do the non-negative check.
1053 // TODO: maybe this wasn't worth it?
1054 StringAppendF(msg, "%d", arg.z);
1055 break;
1056 case 'p': // void* ("pointer")
1057 if (arg.p == nullptr) {
1058 *msg += "NULL";
1059 } else {
1060 StringAppendF(msg, "(void*) %p", arg.p);
1061 }
1062 break;
1063 case 'r': { // jint (release mode)
1064 jint releaseMode = arg.r;
1065 if (releaseMode == 0) {
1066 *msg += "0";
1067 } else if (releaseMode == JNI_ABORT) {
1068 *msg += "JNI_ABORT";
1069 } else if (releaseMode == JNI_COMMIT) {
1070 *msg += "JNI_COMMIT";
1071 } else {
1072 StringAppendF(msg, "invalid release mode %d", releaseMode);
1073 }
1074 break;
1075 }
1076 case 'u': // const char* (Modified UTF-8)
1077 if (arg.u == nullptr) {
1078 *msg += "NULL";
1079 } else {
1080 StringAppendF(msg, "\"%s\"", arg.u);
1081 }
1082 break;
1083 case 'w': // jobjectRefType
1084 switch (arg.w) {
1085 case JNIInvalidRefType:
1086 *msg += "invalid reference type";
1087 break;
1088 case JNILocalRefType:
1089 *msg += "local ref type";
1090 break;
1091 case JNIGlobalRefType:
1092 *msg += "global ref type";
1093 break;
1094 case JNIWeakGlobalRefType:
1095 *msg += "weak global ref type";
1096 break;
1097 default:
1098 *msg += "unknown ref type";
1099 break;
1100 }
1101 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001102 default:
1103 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1104 }
1105 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001106 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001107 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001108 *
1109 * Since we're dealing with objects, switch to "running" mode.
1110 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001111 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001112 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001113 if (UNLIKELY(java_array == nullptr)) {
1114 AbortF("jarray was NULL");
1115 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001116 }
1117
Mathieu Chartier0795f232016-09-27 18:43:30 -07001118 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001119 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001120 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001121 AbortF("jarray is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -07001122 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1123 java_array,
1124 a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001125 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001126 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001127 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001128 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001129 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001130 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001131 }
1132
Ian Rogers68d8b422014-07-17 11:09:10 -07001133 bool CheckBoolean(jboolean z) {
1134 if (z != JNI_TRUE && z != JNI_FALSE) {
1135 AbortF("unexpected jboolean value: %d", z);
1136 return false;
1137 }
1138 return true;
1139 }
1140
1141 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001142 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001143 AbortF("negative jsize: %d", length);
1144 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001145 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001146 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001147 }
1148
Andreas Gampe08883de2016-11-08 13:20:52 -08001149 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001150 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001151 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001152 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001153 }
Andreas Gampe08883de2016-11-08 13:20:52 -08001154 ArtField* f = jni::DecodeArtField(fid);
Mathieu Chartierc7853442015-03-27 14:35:38 -07001155 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001156 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001157 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001158 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001159 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001160 }
1161 return f;
1162 }
1163
Andreas Gampe13b27842016-11-07 16:48:23 -08001164 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001165 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001166 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001167 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001168 }
Andreas Gampe13b27842016-11-07 16:48:23 -08001169 ArtMethod* m = jni::DecodeArtMethod(mid);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001170 // TODO: Better check here.
1171 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001172 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001173 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001174 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001175 }
1176 return m;
1177 }
1178
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001179 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001180 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001181 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001182 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1183 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001184 }
1185
Daniel Erat35e827a2016-05-10 18:07:18 -06001186 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001187 JNIEnvExt* threadEnv = self->GetJniEnv();
1188
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001189 // Verify that the current thread is (a) attached and (b) associated with
1190 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001191 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001192 // Get the thread owning the JNIEnv that's being used.
1193 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self;
Ian Rogers68d8b422014-07-17 11:09:10 -07001194 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001195 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001196 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001197 }
1198
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001199 // Verify that, if this thread previously made a critical "get" call, we
1200 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001201 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001202 case kFlag_CritOkay: // okay to call this method
1203 break;
1204 case kFlag_CritBad: // not okay to call
1205 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001206 AbortF("thread %s using JNI after critical get",
1207 ToStr<Thread>(*self).c_str());
1208 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001209 }
1210 break;
1211 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001212 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001213 threadEnv->critical++;
1214 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001215 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001216 threadEnv->critical--;
1217 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001218 AbortF("thread %s called too many critical releases",
1219 ToStr<Thread>(*self).c_str());
1220 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001221 }
1222 break;
1223 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001224 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001225 }
1226
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001227 // Verify that, if an exception has been raised, the native code doesn't
1228 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001229 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001230 mirror::Throwable* exception = self->GetException();
1231 AbortF("JNI %s called with pending exception %s",
1232 function_name_,
1233 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001234 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001235 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001236 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001237 }
1238
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001239 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001240 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001241 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001242 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001243 AbortF("non-nullable const char* was NULL");
1244 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001245 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001246 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001247 }
1248
Ian Rogersef7d42f2014-01-06 12:55:46 -08001249 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001250 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001251 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001252 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1253 // practice anyways.
1254 std::ostringstream oss;
1255 oss << std::hex;
1256 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1257 while (*tmp != 0) {
1258 if (tmp == utf8) {
1259 oss << "<";
1260 }
1261 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1262 if (tmp == utf8) {
1263 oss << '>';
1264 }
1265 tmp++;
1266 if (*tmp != 0) {
1267 oss << ' ';
1268 }
1269 }
1270
Ian Rogers68d8b422014-07-17 11:09:10 -07001271 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001272 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001273 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001274 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001275 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001276 }
1277
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001278 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1279 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001280 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001281 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001282 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001283 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001284 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001285 case 0x00:
1286 case 0x01:
1287 case 0x02:
1288 case 0x03:
1289 case 0x04:
1290 case 0x05:
1291 case 0x06:
1292 case 0x07:
1293 // Bit pattern 0xxx. No need for any extra bytes.
1294 break;
1295 case 0x08:
1296 case 0x09:
1297 case 0x0a:
1298 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001299 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001300 *errorKind = "start";
1301 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001302 case 0x0f:
1303 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001304 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001305 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1306 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001307 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1308 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001309 *errorKind = "continuation";
1310 return utf8;
1311 }
1312 } else {
1313 *errorKind = "start";
1314 return utf8;
1315 }
1316
1317 // Fall through to the cases below to consume two more continuation bytes.
1318 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001319 case 0x0e:
1320 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001321 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1322 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001323 *errorKind = "continuation";
1324 return utf8;
1325 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001326
1327 // Fall through to consume one more continuation byte.
1328 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001329 case 0x0c:
1330 case 0x0d:
1331 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001332 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1333 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001334 *errorKind = "continuation";
1335 return utf8;
1336 }
1337 break;
1338 }
1339 }
1340 return 0;
1341 }
1342
Ian Rogers68d8b422014-07-17 11:09:10 -07001343 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1344 va_list args;
1345 va_start(args, fmt);
1346 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1347 va_end(args);
1348 }
1349
1350 // The name of the JNI function being checked.
1351 const char* const function_name_;
1352
1353 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001354 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001355
Ian Rogers68d8b422014-07-17 11:09:10 -07001356 const bool has_method_;
1357
Elliott Hughesa2501992011-08-26 19:39:54 -07001358 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1359};
1360
Elliott Hughesa2501992011-08-26 19:39:54 -07001361/*
1362 * ===========================================================================
1363 * Guarded arrays
1364 * ===========================================================================
1365 */
1366
Elliott Hughesa2501992011-08-26 19:39:54 -07001367/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001368class GuardedCopy {
1369 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001370 /*
1371 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1372 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001373 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001374 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001375 const size_t new_len = LengthIncludingRedZones(len);
1376 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001377
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001378 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001379 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001380 if (!mod_okay) {
1381 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001382 }
1383
Ian Rogers68d8b422014-07-17 11:09:10 -07001384 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001385
Ian Rogers68d8b422014-07-17 11:09:10 -07001386 // Fill begin region with canary pattern.
1387 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1388 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1389 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1390 if (kCanary[j] == '\0') {
1391 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001392 } else {
1393 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001394 }
1395 }
1396
1397 // Copy the data in; note "len" could be zero.
1398 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1399
1400 // Fill end region with canary pattern.
1401 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1402 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1403 if (kCanary[j] == '\0') {
1404 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001405 } else {
1406 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001407 }
1408 }
1409
1410 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001411 }
1412
1413 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001414 * Create a guarded copy of a primitive array. Modifications to the copied
1415 * data are allowed. Returns a pointer to the copied data.
1416 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001417 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1418 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001419 ScopedObjectAccess soa(env);
1420
Mathieu Chartier0795f232016-09-27 18:43:30 -07001421 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001422 size_t component_size = a->GetClass()->GetComponentSize();
1423 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001424 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001425 if (is_copy != nullptr) {
1426 *is_copy = JNI_TRUE;
1427 }
1428 return result;
1429 }
1430
1431 /*
1432 * Perform the array "release" operation, which may or may not copy data
1433 * back into the managed heap, and may or may not release the underlying storage.
1434 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001435 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1436 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1437 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001438 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001439 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1440 return nullptr;
1441 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001442 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1443 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001444 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001445 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001446 }
1447 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001448 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001449 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001450 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001451 }
1452
1453
1454 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001455 * Free up the guard buffer, scrub it, and return the original pointer.
1456 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001457 static void* Destroy(void* embedded_buf) {
1458 GuardedCopy* copy = FromEmbedded(embedded_buf);
1459 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1460 size_t len = LengthIncludingRedZones(copy->original_length_);
1461 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001462 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001463 }
1464
1465 /*
1466 * Verify the guard area and, if "modOkay" is false, that the data itself
1467 * has not been altered.
1468 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001469 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001470 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001471 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1472 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1473 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001474 }
1475
1476 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001477 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001478 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1479 }
1480
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001481 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001482 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001483 if (result == MAP_FAILED) {
1484 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1485 }
1486 return reinterpret_cast<uint8_t*>(result);
1487 }
1488
Ian Rogers68d8b422014-07-17 11:09:10 -07001489 static void DebugFree(void* buf, size_t len) {
1490 if (munmap(buf, len) != 0) {
1491 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001492 }
1493 }
1494
Ian Rogers68d8b422014-07-17 11:09:10 -07001495 static size_t LengthIncludingRedZones(size_t len) {
1496 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001497 }
1498
Ian Rogers68d8b422014-07-17 11:09:10 -07001499 // Get the GuardedCopy from the interior pointer.
1500 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1501 return reinterpret_cast<GuardedCopy*>(
1502 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001503 }
1504
Ian Rogers68d8b422014-07-17 11:09:10 -07001505 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1506 return reinterpret_cast<const GuardedCopy*>(
1507 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001508 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001509
1510 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1511 va_list args;
1512 va_start(args, fmt);
1513 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1514 va_end(args);
1515 }
1516
1517 bool CheckHeader(const char* function_name, bool mod_okay) const {
1518 static const uint32_t kMagicCmp = kGuardMagic;
1519
1520 // Before we do anything with "pExtra", check the magic number. We
1521 // do the check with memcmp rather than "==" in case the pointer is
1522 // unaligned. If it points to completely bogus memory we're going
1523 // to crash, but there's no easy way around that.
1524 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1525 uint8_t buf[4];
1526 memcpy(buf, &magic_, 4);
1527 AbortF(function_name,
1528 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1529 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1530 return false;
1531 }
1532
1533 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1534 // told the client that we made a copy, there's no reason they can't alter the buffer.
1535 if (!mod_okay) {
1536 uLong computed_adler =
1537 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1538 if (computed_adler != adler_) {
1539 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1540 computed_adler, adler_, this);
1541 return false;
1542 }
1543 }
1544 return true;
1545 }
1546
1547 bool CheckRedZones(const char* function_name) const {
1548 // Check the begin red zone.
1549 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1550 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1551 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1552 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1553 return false;
1554 }
1555 if (kCanary[j] == '\0') {
1556 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001557 } else {
1558 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001559 }
1560 }
1561
1562 // Check end region.
1563 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1564 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1565 size_t offset_from_buffer_start =
1566 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1567 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1568 offset_from_buffer_start);
1569 return false;
1570 }
1571 if (kCanary[j] == '\0') {
1572 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001573 } else {
1574 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001575 }
1576 }
1577 return true;
1578 }
1579
1580 // Location that canary value will be written before the guarded region.
1581 const char* StartRedZone() const {
1582 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1583 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1584 }
1585
1586 // Return the interior embedded buffer.
1587 const uint8_t* BufferWithinRedZones() const {
1588 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1589 return embedded_buf;
1590 }
1591
1592 // Location that canary value will be written after the guarded region.
1593 const char* EndRedZone() const {
1594 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1595 size_t buf_len = LengthIncludingRedZones(original_length_);
1596 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1597 }
1598
1599 static constexpr size_t kRedZoneSize = 512;
1600 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1601
1602 // Value written before and after the guarded array.
1603 static const char* const kCanary;
1604
1605 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1606
1607 const uint32_t magic_;
1608 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001609 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001610 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001611};
Ian Rogers68d8b422014-07-17 11:09:10 -07001612const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001613
1614/*
1615 * ===========================================================================
1616 * JNI functions
1617 * ===========================================================================
1618 */
1619
1620class CheckJNI {
1621 public:
1622 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001623 ScopedObjectAccess soa(env);
1624 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1625 JniValueType args[1] = {{.E = env }};
1626 if (sc.Check(soa, true, "E", args)) {
1627 JniValueType result;
1628 result.I = baseEnv(env)->GetVersion(env);
1629 if (sc.Check(soa, false, "I", &result)) {
1630 return result.I;
1631 }
1632 }
1633 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001634 }
1635
Ian Rogers68d8b422014-07-17 11:09:10 -07001636 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1637 ScopedObjectAccess soa(env);
1638 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1639 JniValueType args[2] = {{.E = env }, {.p = vm}};
1640 if (sc.Check(soa, true, "Ep", args)) {
1641 JniValueType result;
1642 result.i = baseEnv(env)->GetJavaVM(env, vm);
1643 if (sc.Check(soa, false, "i", &result)) {
1644 return result.i;
1645 }
1646 }
1647 return JNI_ERR;
1648 }
1649
1650 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1651 ScopedObjectAccess soa(env);
1652 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1653 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1654 if (sc.Check(soa, true, "EcpI", args)) {
1655 JniValueType result;
1656 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1657 if (sc.Check(soa, false, "i", &result)) {
1658 return result.i;
1659 }
1660 }
1661 return JNI_ERR;
1662 }
1663
1664 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1665 ScopedObjectAccess soa(env);
1666 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1667 JniValueType args[2] = {{.E = env }, {.c = c}};
1668 if (sc.Check(soa, true, "Ec", args)) {
1669 JniValueType result;
1670 result.i = baseEnv(env)->UnregisterNatives(env, c);
1671 if (sc.Check(soa, false, "i", &result)) {
1672 return result.i;
1673 }
1674 }
1675 return JNI_ERR;
1676 }
1677
1678 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001679 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1680 // know the object is invalid. The spec says that passing invalid objects or even ones that
1681 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001682 ScopedObjectAccess soa(env);
1683 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001684 JniValueType args[2] = {{.E = env }, {.L = obj}};
1685 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001686 JniValueType result;
1687 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1688 if (sc.Check(soa, false, "w", &result)) {
1689 return result.w;
1690 }
1691 }
1692 return JNIInvalidRefType;
1693 }
1694
1695 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1696 jsize bufLen) {
1697 ScopedObjectAccess soa(env);
1698 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1699 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1700 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1701 JniValueType result;
1702 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1703 if (sc.Check(soa, false, "c", &result)) {
1704 return result.c;
1705 }
1706 }
1707 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001708 }
1709
1710 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001711 ScopedObjectAccess soa(env);
1712 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1713 JniValueType args[2] = {{.E = env}, {.u = name}};
1714 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1715 JniValueType result;
1716 result.c = baseEnv(env)->FindClass(env, name);
1717 if (sc.Check(soa, false, "c", &result)) {
1718 return result.c;
1719 }
1720 }
1721 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001722 }
1723
Elliott Hughese84278b2012-03-22 10:06:53 -07001724 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001725 ScopedObjectAccess soa(env);
1726 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1727 JniValueType args[2] = {{.E = env}, {.c = c}};
1728 if (sc.Check(soa, true, "Ec", args)) {
1729 JniValueType result;
1730 result.c = baseEnv(env)->GetSuperclass(env, c);
1731 if (sc.Check(soa, false, "c", &result)) {
1732 return result.c;
1733 }
1734 }
1735 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001736 }
1737
Elliott Hughese84278b2012-03-22 10:06:53 -07001738 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001739 ScopedObjectAccess soa(env);
1740 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1741 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1742 if (sc.Check(soa, true, "Ecc", args)) {
1743 JniValueType result;
1744 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1745 if (sc.Check(soa, false, "b", &result)) {
1746 return result.b;
1747 }
1748 }
1749 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001750 }
1751
1752 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001753 ScopedObjectAccess soa(env);
1754 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1755 JniValueType args[2] = {{.E = env}, {.L = method}};
1756 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1757 JniValueType result;
1758 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1759 if (sc.Check(soa, false, "m", &result)) {
1760 return result.m;
1761 }
1762 }
1763 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001764 }
1765
1766 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001767 ScopedObjectAccess soa(env);
1768 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1769 JniValueType args[2] = {{.E = env}, {.L = field}};
1770 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1771 JniValueType result;
1772 result.f = baseEnv(env)->FromReflectedField(env, field);
1773 if (sc.Check(soa, false, "f", &result)) {
1774 return result.f;
1775 }
1776 }
1777 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001778 }
1779
1780 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001781 ScopedObjectAccess soa(env);
1782 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1783 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1784 if (sc.Check(soa, true, "Ecmb", args)) {
1785 JniValueType result;
1786 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1787 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1788 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1789 return result.L;
1790 }
1791 }
1792 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001793 }
1794
1795 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001796 ScopedObjectAccess soa(env);
1797 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1798 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1799 if (sc.Check(soa, true, "Ecfb", args)) {
1800 JniValueType result;
1801 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1802 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1803 DCHECK(sc.CheckReflectedField(soa, result.L));
1804 return result.L;
1805 }
1806 }
1807 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001808 }
1809
1810 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001811 ScopedObjectAccess soa(env);
1812 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1813 JniValueType args[2] = {{.E = env}, {.t = obj}};
1814 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1815 JniValueType result;
1816 result.i = baseEnv(env)->Throw(env, obj);
1817 if (sc.Check(soa, false, "i", &result)) {
1818 return result.i;
1819 }
1820 }
1821 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001822 }
1823
Elliott Hughese84278b2012-03-22 10:06:53 -07001824 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001825 ScopedObjectAccess soa(env);
1826 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001827 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001828 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1829 JniValueType result;
1830 result.i = baseEnv(env)->ThrowNew(env, c, message);
1831 if (sc.Check(soa, false, "i", &result)) {
1832 return result.i;
1833 }
1834 }
1835 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001836 }
1837
1838 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001839 ScopedObjectAccess soa(env);
1840 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1841 JniValueType args[1] = {{.E = env}};
1842 if (sc.Check(soa, true, "E", args)) {
1843 JniValueType result;
1844 result.t = baseEnv(env)->ExceptionOccurred(env);
1845 if (sc.Check(soa, false, "t", &result)) {
1846 return result.t;
1847 }
1848 }
1849 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001850 }
1851
1852 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001853 ScopedObjectAccess soa(env);
1854 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1855 JniValueType args[1] = {{.E = env}};
1856 if (sc.Check(soa, true, "E", args)) {
1857 JniValueType result;
1858 baseEnv(env)->ExceptionDescribe(env);
1859 result.V = nullptr;
1860 sc.Check(soa, false, "V", &result);
1861 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001862 }
1863
1864 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001865 ScopedObjectAccess soa(env);
1866 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1867 JniValueType args[1] = {{.E = env}};
1868 if (sc.Check(soa, true, "E", args)) {
1869 JniValueType result;
1870 baseEnv(env)->ExceptionClear(env);
1871 result.V = nullptr;
1872 sc.Check(soa, false, "V", &result);
1873 }
1874 }
1875
1876 static jboolean ExceptionCheck(JNIEnv* env) {
1877 ScopedObjectAccess soa(env);
1878 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1879 JniValueType args[1] = {{.E = env}};
1880 if (sc.Check(soa, true, "E", args)) {
1881 JniValueType result;
1882 result.b = baseEnv(env)->ExceptionCheck(env);
1883 if (sc.Check(soa, false, "b", &result)) {
1884 return result.b;
1885 }
1886 }
1887 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001888 }
1889
1890 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001891 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1892 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1893 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001894 ScopedObjectAccess soa(env);
1895 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1896 JniValueType args[2] = {{.E = env}, {.u = msg}};
1897 if (sc.Check(soa, true, "Eu", args)) {
1898 JniValueType result;
1899 baseEnv(env)->FatalError(env, msg);
1900 // Unreachable.
1901 result.V = nullptr;
1902 sc.Check(soa, false, "V", &result);
1903 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001904 }
1905
1906 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001907 ScopedObjectAccess soa(env);
1908 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1909 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1910 if (sc.Check(soa, true, "EI", args)) {
1911 JniValueType result;
1912 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1913 if (sc.Check(soa, false, "i", &result)) {
1914 return result.i;
1915 }
1916 }
1917 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001918 }
1919
1920 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001921 ScopedObjectAccess soa(env);
1922 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1923 JniValueType args[2] = {{.E = env}, {.L = res}};
1924 if (sc.Check(soa, true, "EL", args)) {
1925 JniValueType result;
1926 result.L = baseEnv(env)->PopLocalFrame(env, res);
1927 sc.Check(soa, false, "L", &result);
1928 return result.L;
1929 }
1930 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001931 }
1932
1933 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001934 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001935 }
1936
Ian Rogers68d8b422014-07-17 11:09:10 -07001937 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1938 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001939 }
1940
1941 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001942 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001943 }
1944
Ian Rogers68d8b422014-07-17 11:09:10 -07001945 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1946 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001947 }
1948
Ian Rogers68d8b422014-07-17 11:09:10 -07001949 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1950 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1951 }
1952
1953 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1954 DeleteRef(__FUNCTION__, env, obj, kLocal);
1955 }
1956
1957 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1958 ScopedObjectAccess soa(env);
1959 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1960 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1961 if (sc.Check(soa, true, "EI", args)) {
1962 JniValueType result;
1963 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1964 if (sc.Check(soa, false, "i", &result)) {
1965 return result.i;
1966 }
1967 }
1968 return JNI_ERR;
1969 }
1970
1971 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1972 ScopedObjectAccess soa(env);
1973 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1974 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1975 if (sc.Check(soa, true, "ELL", args)) {
1976 JniValueType result;
1977 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1978 if (sc.Check(soa, false, "b", &result)) {
1979 return result.b;
1980 }
1981 }
1982 return JNI_FALSE;
1983 }
1984
1985 static jobject AllocObject(JNIEnv* env, jclass c) {
1986 ScopedObjectAccess soa(env);
1987 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1988 JniValueType args[2] = {{.E = env}, {.c = c}};
1989 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1990 JniValueType result;
1991 result.L = baseEnv(env)->AllocObject(env, c);
1992 if (sc.Check(soa, false, "L", &result)) {
1993 return result.L;
1994 }
1995 }
1996 return nullptr;
1997 }
1998
1999 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2000 ScopedObjectAccess soa(env);
2001 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002002 VarArgs rest(mid, vargs);
2003 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2004 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002005 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002006 JniValueType result;
2007 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2008 if (sc.Check(soa, false, "L", &result)) {
2009 return result.L;
2010 }
2011 }
2012 return nullptr;
2013 }
2014
2015 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2016 va_list args;
2017 va_start(args, mid);
2018 jobject result = NewObjectV(env, c, mid, args);
2019 va_end(args);
2020 return result;
2021 }
2022
2023 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2024 ScopedObjectAccess soa(env);
2025 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002026 VarArgs rest(mid, vargs);
2027 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2028 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002029 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002030 JniValueType result;
2031 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2032 if (sc.Check(soa, false, "L", &result)) {
2033 return result.L;
2034 }
2035 }
2036 return nullptr;
2037 }
2038
2039 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2040 ScopedObjectAccess soa(env);
2041 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2042 JniValueType args[2] = {{.E = env}, {.L = obj}};
2043 if (sc.Check(soa, true, "EL", args)) {
2044 JniValueType result;
2045 result.c = baseEnv(env)->GetObjectClass(env, obj);
2046 if (sc.Check(soa, false, "c", &result)) {
2047 return result.c;
2048 }
2049 }
2050 return nullptr;
2051 }
2052
2053 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2054 ScopedObjectAccess soa(env);
2055 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2056 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2057 if (sc.Check(soa, true, "ELc", args)) {
2058 JniValueType result;
2059 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2060 if (sc.Check(soa, false, "b", &result)) {
2061 return result.b;
2062 }
2063 }
2064 return JNI_FALSE;
2065 }
2066
2067 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2068 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2069 }
2070
2071 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2072 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2073 }
2074
2075 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2076 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2077 }
2078
2079 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2080 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2081 }
2082
2083#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2084 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2085 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2086 } \
2087 \
2088 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2089 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2090 } \
2091 \
2092 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2093 JniValueType value; \
2094 value.shorty = v; \
2095 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2096 } \
2097 \
2098 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2099 JniValueType value; \
2100 value.shorty = v; \
2101 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2102 }
2103
2104 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2105 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2106 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2107 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2108 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2109 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2110 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2111 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2112 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2113#undef FIELD_ACCESSORS
2114
2115 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2116 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2117 }
2118
2119 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2120 jvalue* vargs) {
2121 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2122 }
2123
2124 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002125 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002126 }
2127
2128 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2129 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2130 }
2131
2132 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2133 va_list vargs) {
2134 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2135 }
2136
2137 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2138 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2139 }
2140
2141 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2142 va_list vargs;
2143 va_start(vargs, mid);
2144 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2145 va_end(vargs);
2146 }
2147
2148 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2149 va_list vargs;
2150 va_start(vargs, mid);
2151 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2152 va_end(vargs);
2153 }
2154
2155 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2156 va_list vargs;
2157 va_start(vargs, mid);
2158 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2159 va_end(vargs);
2160 }
2161
2162#define CALL(rtype, name, ptype, shorty) \
2163 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2164 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2165 } \
2166 \
2167 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2168 jvalue* vargs) { \
2169 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2170 } \
2171 \
2172 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2173 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2174 } \
2175 \
2176 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2177 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2178 } \
2179 \
2180 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2181 va_list vargs) { \
2182 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2183 } \
2184 \
2185 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2186 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2187 } \
2188 \
2189 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2190 va_list vargs; \
2191 va_start(vargs, mid); \
2192 rtype result = \
2193 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2194 va_end(vargs); \
2195 return result; \
2196 } \
2197 \
2198 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2199 ...) { \
2200 va_list vargs; \
2201 va_start(vargs, mid); \
2202 rtype result = \
2203 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2204 va_end(vargs); \
2205 return result; \
2206 } \
2207 \
2208 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2209 va_list vargs; \
2210 va_start(vargs, mid); \
2211 rtype result = \
2212 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2213 va_end(vargs); \
2214 return result; \
2215 }
2216
2217 CALL(jobject, Object, Primitive::kPrimNot, L)
2218 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2219 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2220 CALL(jchar, Char, Primitive::kPrimChar, C)
2221 CALL(jshort, Short, Primitive::kPrimShort, S)
2222 CALL(jint, Int, Primitive::kPrimInt, I)
2223 CALL(jlong, Long, Primitive::kPrimLong, J)
2224 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2225 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2226#undef CALL
2227
2228 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2229 ScopedObjectAccess soa(env);
2230 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2231 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2232 if (sc.Check(soa, true, "Epz", args)) {
2233 JniValueType result;
2234 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2235 if (sc.Check(soa, false, "s", &result)) {
2236 return result.s;
2237 }
2238 }
2239 return nullptr;
2240 }
2241
2242 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2243 ScopedObjectAccess soa(env);
2244 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2245 JniValueType args[2] = {{.E = env}, {.u = chars}};
2246 if (sc.Check(soa, true, "Eu", args)) {
2247 JniValueType result;
2248 // TODO: stale? show pointer and truncate string.
2249 result.s = baseEnv(env)->NewStringUTF(env, chars);
2250 if (sc.Check(soa, false, "s", &result)) {
2251 return result.s;
2252 }
2253 }
2254 return nullptr;
2255 }
2256
2257 static jsize GetStringLength(JNIEnv* env, jstring string) {
2258 ScopedObjectAccess soa(env);
2259 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2260 JniValueType args[2] = {{.E = env}, {.s = string}};
2261 if (sc.Check(soa, true, "Es", args)) {
2262 JniValueType result;
2263 result.z = baseEnv(env)->GetStringLength(env, string);
2264 if (sc.Check(soa, false, "z", &result)) {
2265 return result.z;
2266 }
2267 }
2268 return JNI_ERR;
2269 }
2270
2271 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2272 ScopedObjectAccess soa(env);
2273 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2274 JniValueType args[2] = {{.E = env}, {.s = string}};
2275 if (sc.Check(soa, true, "Es", args)) {
2276 JniValueType result;
2277 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2278 if (sc.Check(soa, false, "z", &result)) {
2279 return result.z;
2280 }
2281 }
2282 return JNI_ERR;
2283 }
2284
2285 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2286 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2287 is_copy, false, false));
2288 }
2289
2290 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2291 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2292 is_copy, true, false));
2293 }
2294
2295 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2296 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2297 is_copy, false, true));
2298 }
2299
2300 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2301 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2302 }
2303
2304 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2305 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2306 }
2307
2308 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2309 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2310 }
2311
2312 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2313 ScopedObjectAccess soa(env);
2314 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2315 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2316 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2317 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2318 if (sc.Check(soa, true, "EsIIp", args)) {
2319 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2320 JniValueType result;
2321 result.V = nullptr;
2322 sc.Check(soa, false, "V", &result);
2323 }
2324 }
2325
2326 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2327 ScopedObjectAccess soa(env);
2328 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2329 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2330 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2331 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2332 if (sc.Check(soa, true, "EsIIp", args)) {
2333 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2334 JniValueType result;
2335 result.V = nullptr;
2336 sc.Check(soa, false, "V", &result);
2337 }
2338 }
2339
2340 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2341 ScopedObjectAccess soa(env);
2342 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2343 JniValueType args[2] = {{.E = env}, {.a = array}};
2344 if (sc.Check(soa, true, "Ea", args)) {
2345 JniValueType result;
2346 result.z = baseEnv(env)->GetArrayLength(env, array);
2347 if (sc.Check(soa, false, "z", &result)) {
2348 return result.z;
2349 }
2350 }
2351 return JNI_ERR;
2352 }
2353
2354 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2355 jobject initial_element) {
2356 ScopedObjectAccess soa(env);
2357 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2358 JniValueType args[4] =
2359 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2360 if (sc.Check(soa, true, "EzcL", args)) {
2361 JniValueType result;
2362 // Note: assignability tests of initial_element are done in the base implementation.
2363 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2364 if (sc.Check(soa, false, "a", &result)) {
2365 return down_cast<jobjectArray>(result.a);
2366 }
2367 }
2368 return nullptr;
2369 }
2370
2371 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2372 ScopedObjectAccess soa(env);
2373 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2374 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2375 if (sc.Check(soa, true, "Eaz", args)) {
2376 JniValueType result;
2377 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2378 if (sc.Check(soa, false, "L", &result)) {
2379 return result.L;
2380 }
2381 }
2382 return nullptr;
2383 }
2384
2385 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2386 ScopedObjectAccess soa(env);
2387 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2388 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2389 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2390 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2391 // in ArrayStoreExceptions.
2392 if (sc.Check(soa, true, "EaIL", args)) {
2393 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2394 JniValueType result;
2395 result.V = nullptr;
2396 sc.Check(soa, false, "V", &result);
2397 }
2398 }
2399
2400 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2401 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2402 Primitive::kPrimBoolean));
2403 }
2404
2405 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2406 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2407 Primitive::kPrimByte));
2408 }
2409
2410 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2411 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2412 Primitive::kPrimChar));
2413 }
2414
2415 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2416 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2417 Primitive::kPrimShort));
2418 }
2419
2420 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2421 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2422 }
2423
2424 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2425 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2426 Primitive::kPrimLong));
2427 }
2428
2429 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2430 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2431 Primitive::kPrimFloat));
2432 }
2433
2434 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2435 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2436 Primitive::kPrimDouble));
2437 }
2438
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002439// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002440#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002441 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2442 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002443 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2444 } \
2445 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002446 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002447 jint mode) { \
2448 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2449 } \
2450 \
2451 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002452 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002453 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2454 } \
2455 \
2456 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2457 const ctype* buf) { \
2458 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2459 }
2460
2461 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2462 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2463 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2464 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2465 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2466 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2467 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2468 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2469#undef PRIMITIVE_ARRAY_FUNCTIONS
2470
2471 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2472 ScopedObjectAccess soa(env);
2473 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2474 JniValueType args[2] = {{.E = env}, {.L = obj}};
2475 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002476 if (obj != nullptr) {
2477 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2478 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002479 JniValueType result;
2480 result.i = baseEnv(env)->MonitorEnter(env, obj);
2481 if (sc.Check(soa, false, "i", &result)) {
2482 return result.i;
2483 }
2484 }
2485 return JNI_ERR;
2486 }
2487
2488 static jint MonitorExit(JNIEnv* env, jobject obj) {
2489 ScopedObjectAccess soa(env);
2490 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2491 JniValueType args[2] = {{.E = env}, {.L = obj}};
2492 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002493 if (obj != nullptr) {
2494 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2495 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002496 JniValueType result;
2497 result.i = baseEnv(env)->MonitorExit(env, obj);
2498 if (sc.Check(soa, false, "i", &result)) {
2499 return result.i;
2500 }
2501 }
2502 return JNI_ERR;
2503 }
2504
2505 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2506 ScopedObjectAccess soa(env);
2507 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2508 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2509 if (sc.Check(soa, true, "Eap", args)) {
2510 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002511 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2512 if (ptr != nullptr && soa.ForceCopy()) {
2513 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002514 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002515 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002516 if (sc.Check(soa, false, "p", &result)) {
2517 return const_cast<void*>(result.p);
2518 }
2519 }
2520 return nullptr;
2521 }
2522
2523 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2524 ScopedObjectAccess soa(env);
2525 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2526 sc.CheckNonNull(carray);
2527 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2528 if (sc.Check(soa, true, "Eapr", args)) {
2529 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002530 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002531 }
2532 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2533 JniValueType result;
2534 result.V = nullptr;
2535 sc.Check(soa, false, "V", &result);
2536 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002537 }
2538
2539 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002540 ScopedObjectAccess soa(env);
2541 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2542 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2543 if (sc.Check(soa, true, "EpJ", args)) {
2544 JniValueType result;
2545 // Note: the validity of address and capacity are checked in the base implementation.
2546 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2547 if (sc.Check(soa, false, "L", &result)) {
2548 return result.L;
2549 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002550 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002551 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002552 }
2553
2554 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002555 ScopedObjectAccess soa(env);
2556 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2557 JniValueType args[2] = {{.E = env}, {.L = buf}};
2558 if (sc.Check(soa, true, "EL", args)) {
2559 JniValueType result;
2560 // Note: this is implemented in the base environment by a GetLongField which will sanity
2561 // check the type of buf in GetLongField above.
2562 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2563 if (sc.Check(soa, false, "p", &result)) {
2564 return const_cast<void*>(result.p);
2565 }
2566 }
2567 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002568 }
2569
2570 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002571 ScopedObjectAccess soa(env);
2572 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2573 JniValueType args[2] = {{.E = env}, {.L = buf}};
2574 if (sc.Check(soa, true, "EL", args)) {
2575 JniValueType result;
2576 // Note: this is implemented in the base environment by a GetIntField which will sanity
2577 // check the type of buf in GetIntField above.
2578 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2579 if (sc.Check(soa, false, "J", &result)) {
2580 return result.J;
2581 }
2582 }
2583 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002584 }
2585
2586 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002587 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2588 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2589 }
2590
2591 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002592 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2593 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002594
2595 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2596 ScopedObjectAccess soa(env);
2597 ScopedCheck sc(kFlag_Default, function_name);
2598 JniValueType args[2] = {{.E = env}, {.L = obj}};
2599 if (sc.Check(soa, true, "EL", args)) {
2600 JniValueType result;
2601 switch (kind) {
2602 case kGlobal:
2603 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2604 break;
2605 case kLocal:
2606 result.L = baseEnv(env)->NewLocalRef(env, obj);
2607 break;
2608 case kWeakGlobal:
2609 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2610 break;
2611 default:
2612 LOG(FATAL) << "Unexpected reference kind: " << kind;
2613 }
2614 if (sc.Check(soa, false, "L", &result)) {
2615 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002616 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002617 return result.L;
2618 }
2619 }
2620 return nullptr;
2621 }
2622
2623 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2624 ScopedObjectAccess soa(env);
2625 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2626 JniValueType args[2] = {{.E = env}, {.L = obj}};
2627 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002628 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002629 JniValueType result;
2630 switch (kind) {
2631 case kGlobal:
2632 baseEnv(env)->DeleteGlobalRef(env, obj);
2633 break;
2634 case kLocal:
2635 baseEnv(env)->DeleteLocalRef(env, obj);
2636 break;
2637 case kWeakGlobal:
2638 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2639 break;
2640 default:
2641 LOG(FATAL) << "Unexpected reference kind: " << kind;
2642 }
2643 result.V = nullptr;
2644 sc.Check(soa, false, "V", &result);
2645 }
2646 }
2647
2648 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2649 const char* name, const char* sig, bool is_static) {
2650 ScopedObjectAccess soa(env);
2651 ScopedCheck sc(kFlag_Default, function_name);
2652 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2653 if (sc.Check(soa, true, "Ecuu", args)) {
2654 JniValueType result;
2655 if (is_static) {
2656 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2657 } else {
2658 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2659 }
2660 if (sc.Check(soa, false, "m", &result)) {
2661 return result.m;
2662 }
2663 }
2664 return nullptr;
2665 }
2666
2667 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2668 const char* name, const char* sig, bool is_static) {
2669 ScopedObjectAccess soa(env);
2670 ScopedCheck sc(kFlag_Default, function_name);
2671 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2672 if (sc.Check(soa, true, "Ecuu", args)) {
2673 JniValueType result;
2674 if (is_static) {
2675 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2676 } else {
2677 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2678 }
2679 if (sc.Check(soa, false, "f", &result)) {
2680 return result.f;
2681 }
2682 }
2683 return nullptr;
2684 }
2685
2686 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2687 bool is_static, Primitive::Type type) {
2688 ScopedObjectAccess soa(env);
2689 ScopedCheck sc(kFlag_Default, function_name);
2690 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2691 JniValueType result;
2692 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2693 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2694 const char* result_check = nullptr;
2695 switch (type) {
2696 case Primitive::kPrimNot:
2697 if (is_static) {
2698 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2699 } else {
2700 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2701 }
2702 result_check = "L";
2703 break;
2704 case Primitive::kPrimBoolean:
2705 if (is_static) {
2706 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2707 } else {
2708 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2709 }
2710 result_check = "Z";
2711 break;
2712 case Primitive::kPrimByte:
2713 if (is_static) {
2714 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2715 } else {
2716 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2717 }
2718 result_check = "B";
2719 break;
2720 case Primitive::kPrimChar:
2721 if (is_static) {
2722 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2723 } else {
2724 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2725 }
2726 result_check = "C";
2727 break;
2728 case Primitive::kPrimShort:
2729 if (is_static) {
2730 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2731 } else {
2732 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2733 }
2734 result_check = "S";
2735 break;
2736 case Primitive::kPrimInt:
2737 if (is_static) {
2738 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2739 } else {
2740 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2741 }
2742 result_check = "I";
2743 break;
2744 case Primitive::kPrimLong:
2745 if (is_static) {
2746 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2747 } else {
2748 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2749 }
2750 result_check = "J";
2751 break;
2752 case Primitive::kPrimFloat:
2753 if (is_static) {
2754 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2755 } else {
2756 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2757 }
2758 result_check = "F";
2759 break;
2760 case Primitive::kPrimDouble:
2761 if (is_static) {
2762 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2763 } else {
2764 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2765 }
2766 result_check = "D";
2767 break;
2768 case Primitive::kPrimVoid:
2769 LOG(FATAL) << "Unexpected type: " << type;
2770 break;
2771 }
2772 if (sc.Check(soa, false, result_check, &result)) {
2773 return result;
2774 }
2775 }
2776 result.J = 0;
2777 return result;
2778 }
2779
2780 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2781 bool is_static, Primitive::Type type, JniValueType value) {
2782 ScopedObjectAccess soa(env);
2783 ScopedCheck sc(kFlag_Default, function_name);
2784 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2785 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2786 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2787 if (sc.Check(soa, true, sig, args) &&
2788 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2789 switch (type) {
2790 case Primitive::kPrimNot:
2791 if (is_static) {
2792 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2793 } else {
2794 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2795 }
2796 break;
2797 case Primitive::kPrimBoolean:
2798 if (is_static) {
2799 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2800 } else {
2801 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2802 }
2803 break;
2804 case Primitive::kPrimByte:
2805 if (is_static) {
2806 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2807 } else {
2808 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2809 }
2810 break;
2811 case Primitive::kPrimChar:
2812 if (is_static) {
2813 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2814 } else {
2815 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2816 }
2817 break;
2818 case Primitive::kPrimShort:
2819 if (is_static) {
2820 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2821 } else {
2822 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2823 }
2824 break;
2825 case Primitive::kPrimInt:
2826 if (is_static) {
2827 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2828 } else {
2829 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2830 }
2831 break;
2832 case Primitive::kPrimLong:
2833 if (is_static) {
2834 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2835 } else {
2836 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2837 }
2838 break;
2839 case Primitive::kPrimFloat:
2840 if (is_static) {
2841 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2842 } else {
2843 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2844 }
2845 break;
2846 case Primitive::kPrimDouble:
2847 if (is_static) {
2848 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2849 } else {
2850 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2851 }
2852 break;
2853 case Primitive::kPrimVoid:
2854 LOG(FATAL) << "Unexpected type: " << type;
2855 break;
2856 }
2857 JniValueType result;
2858 result.V = nullptr;
2859 sc.Check(soa, false, "V", &result);
2860 }
2861 }
2862
2863 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07002864 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07002865 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002866 bool checked;
2867 switch (invoke) {
2868 case kVirtual: {
2869 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002870 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2871 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002872 break;
2873 }
2874 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07002875 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2876 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002877 break;
2878 }
2879 case kStatic: {
2880 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002881 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2882 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002883 break;
2884 }
2885 default:
2886 LOG(FATAL) << "Unexpected invoke: " << invoke;
2887 checked = false;
2888 break;
2889 }
2890 return checked;
2891 }
2892
2893 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2894 jmethodID mid, jvalue* vargs, Primitive::Type type,
2895 InvokeType invoke) {
2896 ScopedObjectAccess soa(env);
2897 ScopedCheck sc(kFlag_Default, function_name);
2898 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07002899 VarArgs rest(mid, vargs);
2900 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002901 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2902 const char* result_check;
2903 switch (type) {
2904 case Primitive::kPrimNot:
2905 result_check = "L";
2906 switch (invoke) {
2907 case kVirtual:
2908 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2909 break;
2910 case kDirect:
2911 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2912 break;
2913 case kStatic:
2914 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2915 break;
2916 default:
2917 break;
2918 }
2919 break;
2920 case Primitive::kPrimBoolean:
2921 result_check = "Z";
2922 switch (invoke) {
2923 case kVirtual:
2924 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2925 break;
2926 case kDirect:
2927 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2928 break;
2929 case kStatic:
2930 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2931 break;
2932 default:
2933 break;
2934 }
2935 break;
2936 case Primitive::kPrimByte:
2937 result_check = "B";
2938 switch (invoke) {
2939 case kVirtual:
2940 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2941 break;
2942 case kDirect:
2943 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2944 break;
2945 case kStatic:
2946 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2947 break;
2948 default:
2949 break;
2950 }
2951 break;
2952 case Primitive::kPrimChar:
2953 result_check = "C";
2954 switch (invoke) {
2955 case kVirtual:
2956 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2957 break;
2958 case kDirect:
2959 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2960 break;
2961 case kStatic:
2962 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2963 break;
2964 default:
2965 break;
2966 }
2967 break;
2968 case Primitive::kPrimShort:
2969 result_check = "S";
2970 switch (invoke) {
2971 case kVirtual:
2972 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2973 break;
2974 case kDirect:
2975 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2976 break;
2977 case kStatic:
2978 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2979 break;
2980 default:
2981 break;
2982 }
2983 break;
2984 case Primitive::kPrimInt:
2985 result_check = "I";
2986 switch (invoke) {
2987 case kVirtual:
2988 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2989 break;
2990 case kDirect:
2991 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2992 break;
2993 case kStatic:
2994 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2995 break;
2996 default:
2997 break;
2998 }
2999 break;
3000 case Primitive::kPrimLong:
3001 result_check = "J";
3002 switch (invoke) {
3003 case kVirtual:
3004 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3005 break;
3006 case kDirect:
3007 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3008 break;
3009 case kStatic:
3010 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3011 break;
3012 default:
3013 break;
3014 }
3015 break;
3016 case Primitive::kPrimFloat:
3017 result_check = "F";
3018 switch (invoke) {
3019 case kVirtual:
3020 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3021 break;
3022 case kDirect:
3023 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3024 break;
3025 case kStatic:
3026 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3027 break;
3028 default:
3029 break;
3030 }
3031 break;
3032 case Primitive::kPrimDouble:
3033 result_check = "D";
3034 switch (invoke) {
3035 case kVirtual:
3036 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3037 break;
3038 case kDirect:
3039 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3040 break;
3041 case kStatic:
3042 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3043 break;
3044 default:
3045 break;
3046 }
3047 break;
3048 case Primitive::kPrimVoid:
3049 result_check = "V";
3050 result.V = nullptr;
3051 switch (invoke) {
3052 case kVirtual:
3053 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3054 break;
3055 case kDirect:
3056 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3057 break;
3058 case kStatic:
3059 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3060 break;
3061 default:
3062 LOG(FATAL) << "Unexpected invoke: " << invoke;
3063 }
3064 break;
3065 default:
3066 LOG(FATAL) << "Unexpected return type: " << type;
3067 result_check = nullptr;
3068 }
3069 if (sc.Check(soa, false, result_check, &result)) {
3070 return result;
3071 }
3072 }
3073 result.J = 0;
3074 return result;
3075 }
3076
3077 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3078 jmethodID mid, va_list vargs, Primitive::Type type,
3079 InvokeType invoke) {
3080 ScopedObjectAccess soa(env);
3081 ScopedCheck sc(kFlag_Default, function_name);
3082 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003083 VarArgs rest(mid, vargs);
3084 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003085 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3086 const char* result_check;
3087 switch (type) {
3088 case Primitive::kPrimNot:
3089 result_check = "L";
3090 switch (invoke) {
3091 case kVirtual:
3092 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3093 break;
3094 case kDirect:
3095 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3096 break;
3097 case kStatic:
3098 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3099 break;
3100 default:
3101 LOG(FATAL) << "Unexpected invoke: " << invoke;
3102 }
3103 break;
3104 case Primitive::kPrimBoolean:
3105 result_check = "Z";
3106 switch (invoke) {
3107 case kVirtual:
3108 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3109 break;
3110 case kDirect:
3111 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3112 break;
3113 case kStatic:
3114 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3115 break;
3116 default:
3117 LOG(FATAL) << "Unexpected invoke: " << invoke;
3118 }
3119 break;
3120 case Primitive::kPrimByte:
3121 result_check = "B";
3122 switch (invoke) {
3123 case kVirtual:
3124 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3125 break;
3126 case kDirect:
3127 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3128 break;
3129 case kStatic:
3130 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3131 break;
3132 default:
3133 LOG(FATAL) << "Unexpected invoke: " << invoke;
3134 }
3135 break;
3136 case Primitive::kPrimChar:
3137 result_check = "C";
3138 switch (invoke) {
3139 case kVirtual:
3140 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3141 break;
3142 case kDirect:
3143 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3144 break;
3145 case kStatic:
3146 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3147 break;
3148 default:
3149 LOG(FATAL) << "Unexpected invoke: " << invoke;
3150 }
3151 break;
3152 case Primitive::kPrimShort:
3153 result_check = "S";
3154 switch (invoke) {
3155 case kVirtual:
3156 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3157 break;
3158 case kDirect:
3159 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3160 break;
3161 case kStatic:
3162 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3163 break;
3164 default:
3165 LOG(FATAL) << "Unexpected invoke: " << invoke;
3166 }
3167 break;
3168 case Primitive::kPrimInt:
3169 result_check = "I";
3170 switch (invoke) {
3171 case kVirtual:
3172 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3173 break;
3174 case kDirect:
3175 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3176 break;
3177 case kStatic:
3178 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3179 break;
3180 default:
3181 LOG(FATAL) << "Unexpected invoke: " << invoke;
3182 }
3183 break;
3184 case Primitive::kPrimLong:
3185 result_check = "J";
3186 switch (invoke) {
3187 case kVirtual:
3188 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3189 break;
3190 case kDirect:
3191 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3192 break;
3193 case kStatic:
3194 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3195 break;
3196 default:
3197 LOG(FATAL) << "Unexpected invoke: " << invoke;
3198 }
3199 break;
3200 case Primitive::kPrimFloat:
3201 result_check = "F";
3202 switch (invoke) {
3203 case kVirtual:
3204 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3205 break;
3206 case kDirect:
3207 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3208 break;
3209 case kStatic:
3210 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3211 break;
3212 default:
3213 LOG(FATAL) << "Unexpected invoke: " << invoke;
3214 }
3215 break;
3216 case Primitive::kPrimDouble:
3217 result_check = "D";
3218 switch (invoke) {
3219 case kVirtual:
3220 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3221 break;
3222 case kDirect:
3223 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3224 break;
3225 case kStatic:
3226 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3227 break;
3228 default:
3229 LOG(FATAL) << "Unexpected invoke: " << invoke;
3230 }
3231 break;
3232 case Primitive::kPrimVoid:
3233 result_check = "V";
3234 result.V = nullptr;
3235 switch (invoke) {
3236 case kVirtual:
3237 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3238 break;
3239 case kDirect:
3240 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3241 break;
3242 case kStatic:
3243 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3244 break;
3245 default:
3246 LOG(FATAL) << "Unexpected invoke: " << invoke;
3247 }
3248 break;
3249 default:
3250 LOG(FATAL) << "Unexpected return type: " << type;
3251 result_check = nullptr;
3252 }
3253 if (sc.Check(soa, false, result_check, &result)) {
3254 return result;
3255 }
3256 }
3257 result.J = 0;
3258 return result;
3259 }
3260
3261 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3262 jboolean* is_copy, bool utf, bool critical) {
3263 ScopedObjectAccess soa(env);
3264 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3265 ScopedCheck sc(flags, function_name);
3266 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3267 if (sc.Check(soa, true, "Esp", args)) {
3268 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003269 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003270 if (utf) {
3271 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003272 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3273 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003274 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003275 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3276 baseEnv(env)->GetStringChars(env, string, is_copy));
3277 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003278 }
3279 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003280 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003281 if (utf) {
3282 size_t length_in_bytes = strlen(result.u) + 1;
3283 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003284 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003285 } else {
3286 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3287 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003288 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003289 }
3290 if (is_copy != nullptr) {
3291 *is_copy = JNI_TRUE;
3292 }
3293 }
3294 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3295 return utf ? result.u : result.p;
3296 }
3297 }
3298 return nullptr;
3299 }
3300
3301 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3302 const void* chars, bool utf, bool critical) {
3303 ScopedObjectAccess soa(env);
3304 int flags = kFlag_ExcepOkay | kFlag_Release;
3305 if (critical) {
3306 flags |= kFlag_CritRelease;
3307 }
3308 ScopedCheck sc(flags, function_name);
3309 sc.CheckNonNull(chars);
3310 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3311 if (force_copy_ok && soa.ForceCopy()) {
3312 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3313 }
3314 if (force_copy_ok) {
3315 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3316 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3317 if (utf) {
3318 CHECK(!critical);
3319 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3320 } else {
3321 if (critical) {
3322 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3323 } else {
3324 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3325 }
3326 }
3327 JniValueType result;
3328 sc.Check(soa, false, "V", &result);
3329 }
3330 }
3331 }
3332
3333 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3334 Primitive::Type type) {
3335 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003336 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003337 JniValueType args[2] = {{.E = env}, {.z = length}};
3338 if (sc.Check(soa, true, "Ez", args)) {
3339 JniValueType result;
3340 switch (type) {
3341 case Primitive::kPrimBoolean:
3342 result.a = baseEnv(env)->NewBooleanArray(env, length);
3343 break;
3344 case Primitive::kPrimByte:
3345 result.a = baseEnv(env)->NewByteArray(env, length);
3346 break;
3347 case Primitive::kPrimChar:
3348 result.a = baseEnv(env)->NewCharArray(env, length);
3349 break;
3350 case Primitive::kPrimShort:
3351 result.a = baseEnv(env)->NewShortArray(env, length);
3352 break;
3353 case Primitive::kPrimInt:
3354 result.a = baseEnv(env)->NewIntArray(env, length);
3355 break;
3356 case Primitive::kPrimLong:
3357 result.a = baseEnv(env)->NewLongArray(env, length);
3358 break;
3359 case Primitive::kPrimFloat:
3360 result.a = baseEnv(env)->NewFloatArray(env, length);
3361 break;
3362 case Primitive::kPrimDouble:
3363 result.a = baseEnv(env)->NewDoubleArray(env, length);
3364 break;
3365 default:
3366 LOG(FATAL) << "Unexpected primitive type: " << type;
3367 }
3368 if (sc.Check(soa, false, "a", &result)) {
3369 return result.a;
3370 }
3371 }
3372 return nullptr;
3373 }
3374
3375 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3376 JNIEnv* env, jarray array, jboolean* is_copy) {
3377 ScopedObjectAccess soa(env);
3378 ScopedCheck sc(kFlag_Default, function_name);
3379 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3380 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3381 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003382 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003383 switch (type) {
3384 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003385 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3386 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003387 break;
3388 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003389 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003390 break;
3391 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003392 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003393 break;
3394 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003395 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003396 break;
3397 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003398 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003399 break;
3400 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003401 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003402 break;
3403 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003404 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003405 break;
3406 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003407 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003408 break;
3409 default:
3410 LOG(FATAL) << "Unexpected primitive type: " << type;
3411 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003412 if (ptr != nullptr && soa.ForceCopy()) {
3413 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003414 if (is_copy != nullptr) {
3415 *is_copy = JNI_TRUE;
3416 }
3417 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003418 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003419 if (sc.Check(soa, false, "p", &result)) {
3420 return const_cast<void*>(result.p);
3421 }
3422 }
3423 return nullptr;
3424 }
3425
3426 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3427 JNIEnv* env, jarray array, void* elems, jint mode) {
3428 ScopedObjectAccess soa(env);
3429 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3430 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3431 if (soa.ForceCopy()) {
3432 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3433 }
3434 if (!soa.ForceCopy() || elems != nullptr) {
3435 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3436 if (sc.Check(soa, true, "Eapr", args)) {
3437 switch (type) {
3438 case Primitive::kPrimBoolean:
3439 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3440 reinterpret_cast<jboolean*>(elems), mode);
3441 break;
3442 case Primitive::kPrimByte:
3443 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3444 reinterpret_cast<jbyte*>(elems), mode);
3445 break;
3446 case Primitive::kPrimChar:
3447 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3448 reinterpret_cast<jchar*>(elems), mode);
3449 break;
3450 case Primitive::kPrimShort:
3451 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3452 reinterpret_cast<jshort*>(elems), mode);
3453 break;
3454 case Primitive::kPrimInt:
3455 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3456 reinterpret_cast<jint*>(elems), mode);
3457 break;
3458 case Primitive::kPrimLong:
3459 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3460 reinterpret_cast<jlong*>(elems), mode);
3461 break;
3462 case Primitive::kPrimFloat:
3463 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3464 reinterpret_cast<jfloat*>(elems), mode);
3465 break;
3466 case Primitive::kPrimDouble:
3467 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3468 reinterpret_cast<jdouble*>(elems), mode);
3469 break;
3470 default:
3471 LOG(FATAL) << "Unexpected primitive type: " << type;
3472 }
3473 JniValueType result;
3474 result.V = nullptr;
3475 sc.Check(soa, false, "V", &result);
3476 }
3477 }
3478 }
3479 }
3480
3481 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3482 jarray array, jsize start, jsize len, void* buf) {
3483 ScopedObjectAccess soa(env);
3484 ScopedCheck sc(kFlag_Default, function_name);
3485 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3486 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3487 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3488 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3489 switch (type) {
3490 case Primitive::kPrimBoolean:
3491 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3492 reinterpret_cast<jboolean*>(buf));
3493 break;
3494 case Primitive::kPrimByte:
3495 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3496 reinterpret_cast<jbyte*>(buf));
3497 break;
3498 case Primitive::kPrimChar:
3499 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3500 reinterpret_cast<jchar*>(buf));
3501 break;
3502 case Primitive::kPrimShort:
3503 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3504 reinterpret_cast<jshort*>(buf));
3505 break;
3506 case Primitive::kPrimInt:
3507 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3508 reinterpret_cast<jint*>(buf));
3509 break;
3510 case Primitive::kPrimLong:
3511 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3512 reinterpret_cast<jlong*>(buf));
3513 break;
3514 case Primitive::kPrimFloat:
3515 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3516 reinterpret_cast<jfloat*>(buf));
3517 break;
3518 case Primitive::kPrimDouble:
3519 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3520 reinterpret_cast<jdouble*>(buf));
3521 break;
3522 default:
3523 LOG(FATAL) << "Unexpected primitive type: " << type;
3524 }
3525 JniValueType result;
3526 result.V = nullptr;
3527 sc.Check(soa, false, "V", &result);
3528 }
3529 }
3530
3531 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3532 jarray array, jsize start, jsize len, const void* buf) {
3533 ScopedObjectAccess soa(env);
3534 ScopedCheck sc(kFlag_Default, function_name);
3535 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3536 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3537 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3538 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3539 switch (type) {
3540 case Primitive::kPrimBoolean:
3541 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3542 reinterpret_cast<const jboolean*>(buf));
3543 break;
3544 case Primitive::kPrimByte:
3545 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3546 reinterpret_cast<const jbyte*>(buf));
3547 break;
3548 case Primitive::kPrimChar:
3549 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3550 reinterpret_cast<const jchar*>(buf));
3551 break;
3552 case Primitive::kPrimShort:
3553 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3554 reinterpret_cast<const jshort*>(buf));
3555 break;
3556 case Primitive::kPrimInt:
3557 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3558 reinterpret_cast<const jint*>(buf));
3559 break;
3560 case Primitive::kPrimLong:
3561 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3562 reinterpret_cast<const jlong*>(buf));
3563 break;
3564 case Primitive::kPrimFloat:
3565 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3566 reinterpret_cast<const jfloat*>(buf));
3567 break;
3568 case Primitive::kPrimDouble:
3569 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3570 reinterpret_cast<const jdouble*>(buf));
3571 break;
3572 default:
3573 LOG(FATAL) << "Unexpected primitive type: " << type;
3574 }
3575 JniValueType result;
3576 result.V = nullptr;
3577 sc.Check(soa, false, "V", &result);
3578 }
3579 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003580};
3581
3582const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003583 nullptr, // reserved0.
3584 nullptr, // reserved1.
3585 nullptr, // reserved2.
3586 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003587 CheckJNI::GetVersion,
3588 CheckJNI::DefineClass,
3589 CheckJNI::FindClass,
3590 CheckJNI::FromReflectedMethod,
3591 CheckJNI::FromReflectedField,
3592 CheckJNI::ToReflectedMethod,
3593 CheckJNI::GetSuperclass,
3594 CheckJNI::IsAssignableFrom,
3595 CheckJNI::ToReflectedField,
3596 CheckJNI::Throw,
3597 CheckJNI::ThrowNew,
3598 CheckJNI::ExceptionOccurred,
3599 CheckJNI::ExceptionDescribe,
3600 CheckJNI::ExceptionClear,
3601 CheckJNI::FatalError,
3602 CheckJNI::PushLocalFrame,
3603 CheckJNI::PopLocalFrame,
3604 CheckJNI::NewGlobalRef,
3605 CheckJNI::DeleteGlobalRef,
3606 CheckJNI::DeleteLocalRef,
3607 CheckJNI::IsSameObject,
3608 CheckJNI::NewLocalRef,
3609 CheckJNI::EnsureLocalCapacity,
3610 CheckJNI::AllocObject,
3611 CheckJNI::NewObject,
3612 CheckJNI::NewObjectV,
3613 CheckJNI::NewObjectA,
3614 CheckJNI::GetObjectClass,
3615 CheckJNI::IsInstanceOf,
3616 CheckJNI::GetMethodID,
3617 CheckJNI::CallObjectMethod,
3618 CheckJNI::CallObjectMethodV,
3619 CheckJNI::CallObjectMethodA,
3620 CheckJNI::CallBooleanMethod,
3621 CheckJNI::CallBooleanMethodV,
3622 CheckJNI::CallBooleanMethodA,
3623 CheckJNI::CallByteMethod,
3624 CheckJNI::CallByteMethodV,
3625 CheckJNI::CallByteMethodA,
3626 CheckJNI::CallCharMethod,
3627 CheckJNI::CallCharMethodV,
3628 CheckJNI::CallCharMethodA,
3629 CheckJNI::CallShortMethod,
3630 CheckJNI::CallShortMethodV,
3631 CheckJNI::CallShortMethodA,
3632 CheckJNI::CallIntMethod,
3633 CheckJNI::CallIntMethodV,
3634 CheckJNI::CallIntMethodA,
3635 CheckJNI::CallLongMethod,
3636 CheckJNI::CallLongMethodV,
3637 CheckJNI::CallLongMethodA,
3638 CheckJNI::CallFloatMethod,
3639 CheckJNI::CallFloatMethodV,
3640 CheckJNI::CallFloatMethodA,
3641 CheckJNI::CallDoubleMethod,
3642 CheckJNI::CallDoubleMethodV,
3643 CheckJNI::CallDoubleMethodA,
3644 CheckJNI::CallVoidMethod,
3645 CheckJNI::CallVoidMethodV,
3646 CheckJNI::CallVoidMethodA,
3647 CheckJNI::CallNonvirtualObjectMethod,
3648 CheckJNI::CallNonvirtualObjectMethodV,
3649 CheckJNI::CallNonvirtualObjectMethodA,
3650 CheckJNI::CallNonvirtualBooleanMethod,
3651 CheckJNI::CallNonvirtualBooleanMethodV,
3652 CheckJNI::CallNonvirtualBooleanMethodA,
3653 CheckJNI::CallNonvirtualByteMethod,
3654 CheckJNI::CallNonvirtualByteMethodV,
3655 CheckJNI::CallNonvirtualByteMethodA,
3656 CheckJNI::CallNonvirtualCharMethod,
3657 CheckJNI::CallNonvirtualCharMethodV,
3658 CheckJNI::CallNonvirtualCharMethodA,
3659 CheckJNI::CallNonvirtualShortMethod,
3660 CheckJNI::CallNonvirtualShortMethodV,
3661 CheckJNI::CallNonvirtualShortMethodA,
3662 CheckJNI::CallNonvirtualIntMethod,
3663 CheckJNI::CallNonvirtualIntMethodV,
3664 CheckJNI::CallNonvirtualIntMethodA,
3665 CheckJNI::CallNonvirtualLongMethod,
3666 CheckJNI::CallNonvirtualLongMethodV,
3667 CheckJNI::CallNonvirtualLongMethodA,
3668 CheckJNI::CallNonvirtualFloatMethod,
3669 CheckJNI::CallNonvirtualFloatMethodV,
3670 CheckJNI::CallNonvirtualFloatMethodA,
3671 CheckJNI::CallNonvirtualDoubleMethod,
3672 CheckJNI::CallNonvirtualDoubleMethodV,
3673 CheckJNI::CallNonvirtualDoubleMethodA,
3674 CheckJNI::CallNonvirtualVoidMethod,
3675 CheckJNI::CallNonvirtualVoidMethodV,
3676 CheckJNI::CallNonvirtualVoidMethodA,
3677 CheckJNI::GetFieldID,
3678 CheckJNI::GetObjectField,
3679 CheckJNI::GetBooleanField,
3680 CheckJNI::GetByteField,
3681 CheckJNI::GetCharField,
3682 CheckJNI::GetShortField,
3683 CheckJNI::GetIntField,
3684 CheckJNI::GetLongField,
3685 CheckJNI::GetFloatField,
3686 CheckJNI::GetDoubleField,
3687 CheckJNI::SetObjectField,
3688 CheckJNI::SetBooleanField,
3689 CheckJNI::SetByteField,
3690 CheckJNI::SetCharField,
3691 CheckJNI::SetShortField,
3692 CheckJNI::SetIntField,
3693 CheckJNI::SetLongField,
3694 CheckJNI::SetFloatField,
3695 CheckJNI::SetDoubleField,
3696 CheckJNI::GetStaticMethodID,
3697 CheckJNI::CallStaticObjectMethod,
3698 CheckJNI::CallStaticObjectMethodV,
3699 CheckJNI::CallStaticObjectMethodA,
3700 CheckJNI::CallStaticBooleanMethod,
3701 CheckJNI::CallStaticBooleanMethodV,
3702 CheckJNI::CallStaticBooleanMethodA,
3703 CheckJNI::CallStaticByteMethod,
3704 CheckJNI::CallStaticByteMethodV,
3705 CheckJNI::CallStaticByteMethodA,
3706 CheckJNI::CallStaticCharMethod,
3707 CheckJNI::CallStaticCharMethodV,
3708 CheckJNI::CallStaticCharMethodA,
3709 CheckJNI::CallStaticShortMethod,
3710 CheckJNI::CallStaticShortMethodV,
3711 CheckJNI::CallStaticShortMethodA,
3712 CheckJNI::CallStaticIntMethod,
3713 CheckJNI::CallStaticIntMethodV,
3714 CheckJNI::CallStaticIntMethodA,
3715 CheckJNI::CallStaticLongMethod,
3716 CheckJNI::CallStaticLongMethodV,
3717 CheckJNI::CallStaticLongMethodA,
3718 CheckJNI::CallStaticFloatMethod,
3719 CheckJNI::CallStaticFloatMethodV,
3720 CheckJNI::CallStaticFloatMethodA,
3721 CheckJNI::CallStaticDoubleMethod,
3722 CheckJNI::CallStaticDoubleMethodV,
3723 CheckJNI::CallStaticDoubleMethodA,
3724 CheckJNI::CallStaticVoidMethod,
3725 CheckJNI::CallStaticVoidMethodV,
3726 CheckJNI::CallStaticVoidMethodA,
3727 CheckJNI::GetStaticFieldID,
3728 CheckJNI::GetStaticObjectField,
3729 CheckJNI::GetStaticBooleanField,
3730 CheckJNI::GetStaticByteField,
3731 CheckJNI::GetStaticCharField,
3732 CheckJNI::GetStaticShortField,
3733 CheckJNI::GetStaticIntField,
3734 CheckJNI::GetStaticLongField,
3735 CheckJNI::GetStaticFloatField,
3736 CheckJNI::GetStaticDoubleField,
3737 CheckJNI::SetStaticObjectField,
3738 CheckJNI::SetStaticBooleanField,
3739 CheckJNI::SetStaticByteField,
3740 CheckJNI::SetStaticCharField,
3741 CheckJNI::SetStaticShortField,
3742 CheckJNI::SetStaticIntField,
3743 CheckJNI::SetStaticLongField,
3744 CheckJNI::SetStaticFloatField,
3745 CheckJNI::SetStaticDoubleField,
3746 CheckJNI::NewString,
3747 CheckJNI::GetStringLength,
3748 CheckJNI::GetStringChars,
3749 CheckJNI::ReleaseStringChars,
3750 CheckJNI::NewStringUTF,
3751 CheckJNI::GetStringUTFLength,
3752 CheckJNI::GetStringUTFChars,
3753 CheckJNI::ReleaseStringUTFChars,
3754 CheckJNI::GetArrayLength,
3755 CheckJNI::NewObjectArray,
3756 CheckJNI::GetObjectArrayElement,
3757 CheckJNI::SetObjectArrayElement,
3758 CheckJNI::NewBooleanArray,
3759 CheckJNI::NewByteArray,
3760 CheckJNI::NewCharArray,
3761 CheckJNI::NewShortArray,
3762 CheckJNI::NewIntArray,
3763 CheckJNI::NewLongArray,
3764 CheckJNI::NewFloatArray,
3765 CheckJNI::NewDoubleArray,
3766 CheckJNI::GetBooleanArrayElements,
3767 CheckJNI::GetByteArrayElements,
3768 CheckJNI::GetCharArrayElements,
3769 CheckJNI::GetShortArrayElements,
3770 CheckJNI::GetIntArrayElements,
3771 CheckJNI::GetLongArrayElements,
3772 CheckJNI::GetFloatArrayElements,
3773 CheckJNI::GetDoubleArrayElements,
3774 CheckJNI::ReleaseBooleanArrayElements,
3775 CheckJNI::ReleaseByteArrayElements,
3776 CheckJNI::ReleaseCharArrayElements,
3777 CheckJNI::ReleaseShortArrayElements,
3778 CheckJNI::ReleaseIntArrayElements,
3779 CheckJNI::ReleaseLongArrayElements,
3780 CheckJNI::ReleaseFloatArrayElements,
3781 CheckJNI::ReleaseDoubleArrayElements,
3782 CheckJNI::GetBooleanArrayRegion,
3783 CheckJNI::GetByteArrayRegion,
3784 CheckJNI::GetCharArrayRegion,
3785 CheckJNI::GetShortArrayRegion,
3786 CheckJNI::GetIntArrayRegion,
3787 CheckJNI::GetLongArrayRegion,
3788 CheckJNI::GetFloatArrayRegion,
3789 CheckJNI::GetDoubleArrayRegion,
3790 CheckJNI::SetBooleanArrayRegion,
3791 CheckJNI::SetByteArrayRegion,
3792 CheckJNI::SetCharArrayRegion,
3793 CheckJNI::SetShortArrayRegion,
3794 CheckJNI::SetIntArrayRegion,
3795 CheckJNI::SetLongArrayRegion,
3796 CheckJNI::SetFloatArrayRegion,
3797 CheckJNI::SetDoubleArrayRegion,
3798 CheckJNI::RegisterNatives,
3799 CheckJNI::UnregisterNatives,
3800 CheckJNI::MonitorEnter,
3801 CheckJNI::MonitorExit,
3802 CheckJNI::GetJavaVM,
3803 CheckJNI::GetStringRegion,
3804 CheckJNI::GetStringUTFRegion,
3805 CheckJNI::GetPrimitiveArrayCritical,
3806 CheckJNI::ReleasePrimitiveArrayCritical,
3807 CheckJNI::GetStringCritical,
3808 CheckJNI::ReleaseStringCritical,
3809 CheckJNI::NewWeakGlobalRef,
3810 CheckJNI::DeleteWeakGlobalRef,
3811 CheckJNI::ExceptionCheck,
3812 CheckJNI::NewDirectByteBuffer,
3813 CheckJNI::GetDirectBufferAddress,
3814 CheckJNI::GetDirectBufferCapacity,
3815 CheckJNI::GetObjectRefType,
3816};
3817
3818const JNINativeInterface* GetCheckJniNativeInterface() {
3819 return &gCheckNativeInterface;
3820}
3821
3822class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003823 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003824 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003825 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3826 JniValueType args[1] = {{.v = vm}};
3827 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3828 JniValueType result;
3829 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003830 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3831 // which will delete the JavaVMExt.
3832 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003833 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003834 }
3835
3836 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003837 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3838 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3839 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3840 JniValueType result;
3841 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3842 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3843 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003844 }
3845
3846 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003847 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3848 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3849 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3850 JniValueType result;
3851 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3852 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3853 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003854 }
3855
3856 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003857 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3858 JniValueType args[1] = {{.v = vm}};
3859 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3860 JniValueType result;
3861 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3862 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3863 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003864 }
3865
Ian Rogers68d8b422014-07-17 11:09:10 -07003866 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3867 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3868 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3869 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3870 JniValueType result;
3871 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3872 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3873 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003874 }
3875
3876 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003877 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3878 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003879 }
3880};
3881
3882const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003883 nullptr, // reserved0
3884 nullptr, // reserved1
3885 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003886 CheckJII::DestroyJavaVM,
3887 CheckJII::AttachCurrentThread,
3888 CheckJII::DetachCurrentThread,
3889 CheckJII::GetEnv,
3890 CheckJII::AttachCurrentThreadAsDaemon
3891};
3892
3893const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3894 return &gCheckInvokeInterface;
3895}
3896
3897} // namespace art