blob: fe5b765a3a2b010ee09a87549a62e6834836f657 [file] [log] [blame]
Elliott Hughesa2501992011-08-26 19:39:54 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "check_jni.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070018
19#include <sys/mman.h>
20#include <zlib.h>
21
Elliott Hughes07ed66b2012-12-12 18:34:25 -080022#include "base/logging.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070023#include "base/to_str.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070024#include "class_linker.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080025#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070026#include "dex_file-inl.h"
Ian Rogers22d5e732014-07-15 22:23:51 -070027#include "field_helper.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070028#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070029#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080030#include "jni_internal.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070031#include "mirror/art_field-inl.h"
32#include "mirror/art_method-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080033#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034#include "mirror/object-inl.h"
35#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070036#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080037#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070038#include "runtime.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070039#include "scoped_thread_state_change.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070040#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070041#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070042
43namespace art {
44
Elliott Hughesa2501992011-08-26 19:39:54 -070045/*
46 * ===========================================================================
47 * JNI function helpers
48 * ===========================================================================
49 */
50
Elliott Hughes3f6635a2012-06-19 13:37:49 -070051// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -070052#define kFlag_Default 0x0000
53
Elliott Hughes3f6635a2012-06-19 13:37:49 -070054#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
55#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
56#define kFlag_CritGet 0x0002 // This is a critical "get".
57#define kFlag_CritRelease 0x0003 // This is a critical "release".
58#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
Elliott Hughesa2501992011-08-26 19:39:54 -070059
Elliott Hughes3f6635a2012-06-19 13:37:49 -070060#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
61#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -070062
Elliott Hughes3f6635a2012-06-19 13:37:49 -070063#define kFlag_Release 0x0010 // Are we in a non-critical release function?
64#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -070065
Elliott Hughes3f6635a2012-06-19 13:37:49 -070066#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -070067
Elliott Hughes485cac42011-12-09 17:49:35 -080068#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
Ian Rogers68d8b422014-07-17 11:09:10 -070069/*
70 * Java primitive types:
71 * B - jbyte
72 * C - jchar
73 * D - jdouble
74 * F - jfloat
75 * I - jint
76 * J - jlong
77 * S - jshort
78 * Z - jboolean (shown as true and false)
79 * V - void
80 *
81 * Java reference types:
82 * L - jobject
83 * a - jarray
84 * c - jclass
85 * s - jstring
86 * t - jthrowable
87 *
88 * JNI types:
89 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
90 * f - jfieldID
91 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
92 * m - jmethodID
93 * p - void*
94 * r - jint (for release mode arguments)
95 * u - const char* (Modified UTF-8)
96 * z - jsize (for lengths; use i if negative values are okay)
97 * v - JavaVM*
98 * w - jobjectRefType
99 * E - JNIEnv*
100 * . - no argument; just print "..." (used for varargs JNI calls)
101 *
102 */
103union JniValueType {
104 jarray a;
105 jboolean b;
106 jclass c;
107 jfieldID f;
108 jint i;
109 jmethodID m;
110 const void* p; // Pointer.
111 jint r; // Release mode.
112 jstring s;
113 jthrowable t;
114 const char* u; // Modified UTF-8.
115 JavaVM* v;
116 jobjectRefType w;
117 jsize z;
118 jbyte B;
119 jchar C;
120 jdouble D;
121 JNIEnv* E;
122 jfloat F;
123 jint I;
124 jlong J;
125 jobject L;
126 jshort S;
127 const void* V; // void
128 jboolean Z;
Elliott Hughesa0957642011-09-02 14:27:33 -0700129};
130
Elliott Hughesa2501992011-08-26 19:39:54 -0700131class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800132 public:
Ian Rogers68d8b422014-07-17 11:09:10 -0700133 explicit ScopedCheck(int flags, const char* functionName, bool has_method = true)
134 : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700135 }
136
Ian Rogers68d8b422014-07-17 11:09:10 -0700137 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700138
Elliott Hughes81ff3182012-03-23 20:35:56 -0700139 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
140 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
141 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
142 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700143 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700144 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700145 AbortF("illegal class name '%s'\n"
146 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
147 class_name);
148 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700149 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700150 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700151 }
152
153 /*
154 * Verify that this instance field ID is valid for this object.
155 *
156 * Assumes "jobj" has already been validated.
157 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700158 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700159 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700160 mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
161 if (o == nullptr) {
162 AbortF("field operation on NULL object: %p", java_object);
163 return false;
164 }
165 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700166 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700167 AbortF("field operation on invalid %s: %p",
168 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
169 java_object);
170 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700171 }
172
Ian Rogers68d8b422014-07-17 11:09:10 -0700173 mirror::ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800174 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700175 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700176 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800177 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700178 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700179 AbortF("jfieldID %s not valid for an object of class %s",
180 PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
181 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700182 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700183 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700184 }
185
186 /*
187 * Verify that the pointer value is non-NULL.
188 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700189 bool CheckNonNull(const void* ptr) {
190 if (UNLIKELY(ptr == nullptr)) {
191 AbortF("non-nullable argument was NULL");
192 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700193 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700194 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700195 }
196
197 /*
198 * Verify that the method's return type matches the type of call.
199 * 'expectedType' will be "L" for all objects, including arrays.
200 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700201 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
202 jmethodID mid, Primitive::Type type, InvokeType invoke)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700203 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700204 mirror::ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800205 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700206 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700207 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700208 if (type != Primitive::GetType(m->GetShorty()[0])) {
209 AbortF("the return type of %s does not match %s", function_name_, PrettyMethod(m).c_str());
210 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700211 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700212 bool is_static = (invoke == kStatic);
213 if (is_static != m->IsStatic()) {
214 if (is_static) {
215 AbortF("calling non-static method %s with %s",
216 PrettyMethod(m).c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700217 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700218 AbortF("calling static method %s with %s",
219 PrettyMethod(m).c_str(), function_name_);
220 }
221 return false;
222 }
223 if (invoke != kVirtual) {
224 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
225 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
226 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
227 PrettyMethod(m).c_str(), PrettyClass(c).c_str());
228 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700229 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700230 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700231 if (invoke != kStatic) {
232 mirror::Object* o = soa.Decode<mirror::Object*>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700233 if (o == nullptr) {
234 AbortF("can't call %s on null object", PrettyMethod(m).c_str());
235 return false;
236 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700237 AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
238 return false;
239 }
240 }
241 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700242 }
243
244 /*
245 * Verify that this static field ID is valid for this class.
246 *
247 * Assumes "java_class" has already been validated.
248 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700249 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700250 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700251 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
252 mirror::ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800253 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700254 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700255 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700256 if (f->GetDeclaringClass() != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700257 AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
258 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700259 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700260 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700261 }
262
263 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700264 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700265 *
266 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700267 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700268 * allow bad code in the system though.
269 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700270 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700271 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700272 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700273 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700274 mirror::ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800275 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700276 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700277 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700278 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700279 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700280 AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
281 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700282 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700283 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700284 }
285
286 /*
287 * Verify that "mid" is appropriate for "jobj".
288 *
289 * Make sure the object is an instance of the method's declaring class.
290 * (Note the mid might point to a declaration in an interface; this
291 * will be handled automatically by the instanceof check.)
292 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700293 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700294 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700295 mirror::ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800296 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700297 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700298 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700299 mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700300 if (o == nullptr) {
301 AbortF("can't call %s on null object", PrettyMethod(m).c_str());
302 return false;
303 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700304 AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
305 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700306 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700307 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700308 }
309
310 /**
311 * The format string is a sequence of the following characters,
312 * and must be followed by arguments of the corresponding types
313 * in the same order.
314 *
315 * Java primitive types:
316 * B - jbyte
317 * C - jchar
318 * D - jdouble
319 * F - jfloat
320 * I - jint
321 * J - jlong
322 * S - jshort
323 * Z - jboolean (shown as true and false)
324 * V - void
325 *
326 * Java reference types:
327 * L - jobject
328 * a - jarray
329 * c - jclass
330 * s - jstring
331 *
332 * JNI types:
333 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
334 * f - jfieldID
335 * m - jmethodID
336 * p - void*
337 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700338 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700339 * z - jsize (for lengths; use i if negative values are okay)
340 * v - JavaVM*
341 * E - JNIEnv*
342 * . - no argument; just print "..." (used for varargs JNI calls)
343 *
344 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
345 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700346 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
347 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800348 mirror::ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700349 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700350 // We need to guard some of the invocation interface's calls: a bad caller might
351 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700352 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800353 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
354 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700355 }
356 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700357
Ian Rogersef7d42f2014-01-06 12:55:46 -0800358 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700359 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700360 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700361 for (size_t i = 0; fmt[i] != '\0'; ++i) {
362 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
363 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700364 StringAppendF(&msg, ", ");
365 }
366 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700367
Elliott Hughes485cac42011-12-09 17:49:35 -0800368 if ((flags_ & kFlag_ForceTrace) != 0) {
369 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
370 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700371 if (has_method_) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700372 std::string methodName(PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700373 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
374 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700375 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700376 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
377 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700378 }
379 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700380 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700381 }
382 }
383
384 // We always do the thorough checks on entry, and never on exit...
385 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700386 for (size_t i = 0; fmt[i] != '\0'; ++i) {
387 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
388 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700389 }
390 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700391 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700392 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700393 }
394
Ian Rogers68d8b422014-07-17 11:09:10 -0700395 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
396 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
397 if (!should_trace && vm->IsTracingEnabled()) {
398 // We need to guard some of the invocation interface's calls: a bad caller might
399 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
400 Thread* self = Thread::Current();
401 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
402 ScopedObjectAccess soa(self);
403 mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
404 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
405 }
406 }
407 if (should_trace) {
408 std::string msg;
409 for (size_t i = 0; fmt[i] != '\0'; ++i) {
410 TraceNonHeapValue(fmt[i], args[i], &msg);
411 if (fmt[i + 1] != '\0') {
412 StringAppendF(&msg, ", ");
413 }
414 }
415
416 if ((flags_ & kFlag_ForceTrace) != 0) {
417 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
418 } else if (entry) {
419 if (has_method_) {
420 Thread* self = Thread::Current();
421 ScopedObjectAccess soa(self);
422 mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
423 std::string methodName(PrettyMethod(traceMethod, false));
424 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
425 indent_ = methodName.size() + 1;
426 } else {
427 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
428 indent_ = 0;
429 }
430 } else {
431 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
432 }
433 }
434
435 // We always do the thorough checks on entry, and never on exit...
436 if (entry) {
437 for (size_t i = 0; fmt[i] != '\0'; ++i) {
438 if (!CheckNonHeapValue(fmt[i], args[i])) {
439 return false;
440 }
441 }
442 }
443 return true;
444 }
445
446 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
447 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
448 mirror::Object* method = soa.Decode<mirror::Object*>(jmethod);
449 if (method == nullptr) {
450 AbortF("expected non-null method");
451 return false;
452 }
453 mirror::Class* c = method->GetClass();
454 if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method) != c &&
455 soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
456 AbortF("expected java.lang.reflect.Method or "
457 "java.lang.reflect.Constructor but got object of type %s: %p",
458 PrettyTypeOf(method).c_str(), jmethod);
459 return false;
460 }
461 return true;
462 }
463
464 bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
465 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
466 mirror::ArtMethod* method = soa.DecodeMethod(mid);
467 if (method == nullptr) {
468 AbortF("expected non-null constructor");
469 return false;
470 }
471 if (!method->IsConstructor() || method->IsStatic()) {
472 AbortF("expected a constructor but %s: %p", PrettyTypeOf(method).c_str(), mid);
473 return false;
474 }
475 return true;
476 }
477
478 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
479 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
480 mirror::Object* field = soa.Decode<mirror::Object*>(jfield);
481 if (field == nullptr) {
482 AbortF("expected non-null java.lang.reflect.Field");
483 return false;
484 }
485 mirror::Class* c = field->GetClass();
486 if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Field) != c) {
487 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
488 PrettyTypeOf(field).c_str(), jfield);
489 return false;
490 }
491 return true;
492 }
493
494 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
495 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
496 mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
497 if (!obj->GetClass()->IsThrowableClass()) {
498 AbortF("expected java.lang.Throwable but got object of type "
499 "%s: %p", PrettyTypeOf(obj).c_str(), obj);
500 return false;
501 }
502 return true;
503 }
504
505 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
506 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
507 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
508 if (!c->IsThrowableClass()) {
509 AbortF("expected java.lang.Throwable class but got object of "
510 "type %s: %p", PrettyDescriptor(c).c_str(), c);
511 return false;
512 }
513 return true;
514 }
515
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700516 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700517 IndirectRefKind found_kind;
518 if (expected_kind == kLocal) {
519 found_kind = GetIndirectRefKind(obj);
520 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
521 found_kind = kLocal;
522 }
523 } else {
524 found_kind = GetIndirectRefKind(obj);
525 }
526 if (obj != nullptr && found_kind != expected_kind) {
527 AbortF("expected reference of kind %s but found %s: %p",
528 ToStr<IndirectRefKind>(expected_kind).c_str(),
529 ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(),
530 obj);
531 return false;
532 }
533 return true;
534 }
535
536 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
537 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
538 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
539 if (!c->IsInstantiableNonArray()) {
540 AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c);
541 return false;
542 }
543 return true;
544 }
545
546 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
547 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
548 if (!CheckArray(soa, array)) {
549 return false;
550 }
551 mirror::Array* a = soa.Decode<mirror::Array*>(array);
552 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
553 AbortF("incompatible array type %s expected %s[]: %p",
554 PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array);
555 return false;
556 }
557 return true;
558 }
559
560 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
561 Primitive::Type type)
562 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
563 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
564 return false;
565 }
566 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
567 return false;
568 }
569 mirror::ArtField* field = soa.DecodeField(fid);
570 DCHECK(field != nullptr); // Already checked by Check.
571 if (is_static != field->IsStatic()) {
572 AbortF("attempt to access %s field %s: %p",
573 field->IsStatic() ? "static" : "non-static", PrettyField(field).c_str(), fid);
574 return false;
575 }
576 if (type != field->GetTypeAsPrimitiveType()) {
577 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
578 PrettyField(field).c_str(), PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
579 PrettyDescriptor(type).c_str(), fid);
580 return false;
581 }
582 if (is_static) {
583 mirror::Object* o = soa.Decode<mirror::Object*>(obj);
584 if (o == nullptr || !o->IsClass()) {
585 AbortF("attempt to access static field %s with a class argument of type %s: %p",
586 PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
587 return false;
588 }
589 mirror::Class* c = o->AsClass();
590 if (field->GetDeclaringClass() != c) {
591 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
592 PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid);
593 return false;
594 }
595 } else {
596 mirror::Object* o = soa.Decode<mirror::Object*>(obj);
597 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
598 AbortF("attempt to access field %s from an object argument of type %s: %p",
599 PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
600 return false;
601 }
602 }
603 return true;
604 }
605
606 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800607 enum InstanceKind {
608 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700609 kDirectByteBuffer,
610 kObject,
611 kString,
612 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800613 };
614
615 /*
616 * Verify that "jobj" is a valid non-NULL object reference, and points to
617 * an instance of expectedClass.
618 *
619 * Because we're looking at an object on the GC heap, we have to switch
620 * to "running" mode before doing the checks.
621 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700622 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700623 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800624 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800625 switch (kind) {
626 case kClass:
627 what = "jclass";
628 break;
629 case kDirectByteBuffer:
630 what = "direct ByteBuffer";
631 break;
632 case kObject:
633 what = "jobject";
634 break;
635 case kString:
636 what = "jstring";
637 break;
638 case kThrowable:
639 what = "jthrowable";
640 break;
641 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700642 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800643 }
644
Ian Rogersef7d42f2014-01-06 12:55:46 -0800645 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700646 if (null_ok) {
647 return true;
648 } else {
649 AbortF("%s received NULL %s", function_name_, what);
650 return false;
651 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800652 }
653
Ian Rogers68d8b422014-07-17 11:09:10 -0700654 mirror::Object* obj = soa.Decode<mirror::Object*>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700655 if (obj == nullptr) {
656 // Either java_object is invalid or is a cleared weak.
657 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
658 bool okay;
659 if (GetIndirectRefKind(ref) != kWeakGlobal) {
660 okay = false;
661 } else {
662 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
663 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
664 }
665 if (!okay) {
666 AbortF("%s is an invalid %s: %p (%p)",
667 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
668 java_object, obj);
669 return false;
670 }
671 }
672
Mathieu Chartier590fee92013-09-13 13:46:47 -0700673 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700674 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700675 AbortF("%s is an invalid %s: %p (%p)",
676 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
677 java_object, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800678 return false;
679 }
680
681 bool okay = true;
682 switch (kind) {
683 case kClass:
684 okay = obj->IsClass();
685 break;
686 case kDirectByteBuffer:
687 UNIMPLEMENTED(FATAL);
688 break;
689 case kString:
690 okay = obj->GetClass()->IsStringClass();
691 break;
692 case kThrowable:
693 okay = obj->GetClass()->IsThrowableClass();
694 break;
695 case kObject:
696 break;
697 }
698 if (!okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700699 AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800700 return false;
701 }
702
703 return true;
704 }
705
Ian Rogers68d8b422014-07-17 11:09:10 -0700706 /*
707 * Verify that the "mode" argument passed to a primitive array Release
708 * function is one of the valid values.
709 */
710 bool CheckReleaseMode(jint mode) {
711 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
712 AbortF("unknown value for release mode: %d", mode);
713 return false;
714 }
715 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700716 }
717
Ian Rogers68d8b422014-07-17 11:09:10 -0700718 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
719 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
720 switch (fmt) {
721 case 'a': // jarray
722 return CheckArray(soa, arg.a);
723 case 'c': // jclass
724 return CheckInstance(soa, kClass, arg.c, false);
725 case 'f': // jfieldID
726 return CheckFieldID(soa, arg.f) != nullptr;
727 case 'm': // jmethodID
728 return CheckMethodID(soa, arg.m) != nullptr;
729 case 'r': // release int
730 return CheckReleaseMode(arg.r);
731 case 's': // jstring
732 return CheckInstance(soa, kString, arg.s, false);
733 case 't': // jthrowable
734 return CheckInstance(soa, kThrowable, arg.t, false);
735 case 'E': // JNIEnv*
736 return CheckThread(arg.E);
737 case 'L': // jobject
738 return CheckInstance(soa, kObject, arg.L, true);
739 default:
740 return CheckNonHeapValue(fmt, arg);
741 }
742 }
743
744 bool CheckNonHeapValue(char fmt, JniValueType arg) {
745 switch (fmt) {
746 case '.': // ...
747 case 'p': // TODO: pointer - null or readable?
748 case 'v': // JavaVM*
749 case 'B': // jbyte
750 case 'C': // jchar
751 case 'D': // jdouble
752 case 'F': // jfloat
753 case 'I': // jint
754 case 'J': // jlong
755 case 'S': // jshort
756 break; // Ignored.
757 case 'b': // jboolean, why two? Fall-through.
758 case 'Z':
759 return CheckBoolean(arg.Z);
760 case 'u': // utf8
761 if ((flags_ & kFlag_Release) != 0) {
762 return CheckNonNull(arg.u);
763 } else {
764 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
765 return CheckUtfString(arg.u, nullable);
766 }
767 case 'w': // jobjectRefType
768 switch (arg.w) {
769 case JNIInvalidRefType:
770 case JNILocalRefType:
771 case JNIGlobalRefType:
772 case JNIWeakGlobalRefType:
773 break;
774 default:
775 AbortF("Unknown reference type");
776 return false;
777 }
778 break;
779 case 'z': // jsize
780 return CheckLengthPositive(arg.z);
781 default:
782 AbortF("unknown format specifier: '%c'", fmt);
783 return false;
784 }
785 return true;
786 }
787
788 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
789 std::string* msg)
790 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
791 switch (fmt) {
792 case 'L': // jobject fall-through.
793 case 'a': // jarray fall-through.
794 case 's': // jstring fall-through.
795 case 't': // jthrowable fall-through.
796 if (arg.L == nullptr) {
797 *msg += "NULL";
798 } else {
799 StringAppendF(msg, "%p", arg.L);
800 }
801 break;
802 case 'c': { // jclass
803 jclass jc = arg.c;
804 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
805 if (c == nullptr) {
806 *msg += "NULL";
Ian Rogersc0542af2014-09-03 16:16:56 -0700807 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700808 StringAppendF(msg, "INVALID POINTER:%p", jc);
809 } else if (!c->IsClass()) {
810 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
811 } else {
812 *msg += PrettyClass(c);
813 if (!entry) {
814 StringAppendF(msg, " (%p)", jc);
815 }
816 }
817 break;
818 }
819 case 'f': { // jfieldID
820 jfieldID fid = arg.f;
821 mirror::ArtField* f = soa.DecodeField(fid);
822 *msg += PrettyField(f);
823 if (!entry) {
824 StringAppendF(msg, " (%p)", fid);
825 }
826 break;
827 }
828 case 'm': { // jmethodID
829 jmethodID mid = arg.m;
830 mirror::ArtMethod* m = soa.DecodeMethod(mid);
831 *msg += PrettyMethod(m);
832 if (!entry) {
833 StringAppendF(msg, " (%p)", mid);
834 }
835 break;
836 }
837 default:
838 TraceNonHeapValue(fmt, arg, msg);
839 break;
840 }
841 }
842
843 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
844 switch (fmt) {
845 case 'B': // jbyte
846 if (arg.B >= 0 && arg.B < 10) {
847 StringAppendF(msg, "%d", arg.B);
848 } else {
849 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
850 }
851 break;
852 case 'C': // jchar
853 if (arg.C < 0x7f && arg.C >= ' ') {
854 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
855 } else {
856 StringAppendF(msg, "U+%x", arg.C);
857 }
858 break;
859 case 'F': // jfloat
860 StringAppendF(msg, "%g", arg.F);
861 break;
862 case 'D': // jdouble
863 StringAppendF(msg, "%g", arg.D);
864 break;
865 case 'S': // jshort
866 StringAppendF(msg, "%d", arg.S);
867 break;
868 case 'i': // jint - fall-through.
869 case 'I': // jint
870 StringAppendF(msg, "%d", arg.I);
871 break;
872 case 'J': // jlong
873 StringAppendF(msg, "%" PRId64, arg.J);
874 break;
875 case 'Z': // jboolean
876 case 'b': // jboolean (JNI-style)
877 *msg += arg.b == JNI_TRUE ? "true" : "false";
878 break;
879 case 'V': // void
880 DCHECK(arg.V == nullptr);
881 *msg += "void";
882 break;
883 case 'v': // JavaVM*
884 StringAppendF(msg, "(JavaVM*)%p", arg.v);
885 break;
886 case 'E':
887 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
888 break;
889 case 'z': // non-negative jsize
890 // You might expect jsize to be size_t, but it's not; it's the same as jint.
891 // We only treat this specially so we can do the non-negative check.
892 // TODO: maybe this wasn't worth it?
893 StringAppendF(msg, "%d", arg.z);
894 break;
895 case 'p': // void* ("pointer")
896 if (arg.p == nullptr) {
897 *msg += "NULL";
898 } else {
899 StringAppendF(msg, "(void*) %p", arg.p);
900 }
901 break;
902 case 'r': { // jint (release mode)
903 jint releaseMode = arg.r;
904 if (releaseMode == 0) {
905 *msg += "0";
906 } else if (releaseMode == JNI_ABORT) {
907 *msg += "JNI_ABORT";
908 } else if (releaseMode == JNI_COMMIT) {
909 *msg += "JNI_COMMIT";
910 } else {
911 StringAppendF(msg, "invalid release mode %d", releaseMode);
912 }
913 break;
914 }
915 case 'u': // const char* (Modified UTF-8)
916 if (arg.u == nullptr) {
917 *msg += "NULL";
918 } else {
919 StringAppendF(msg, "\"%s\"", arg.u);
920 }
921 break;
922 case 'w': // jobjectRefType
923 switch (arg.w) {
924 case JNIInvalidRefType:
925 *msg += "invalid reference type";
926 break;
927 case JNILocalRefType:
928 *msg += "local ref type";
929 break;
930 case JNIGlobalRefType:
931 *msg += "global ref type";
932 break;
933 case JNIWeakGlobalRefType:
934 *msg += "weak global ref type";
935 break;
936 default:
937 *msg += "unknown ref type";
938 break;
939 }
940 break;
941 case '.':
942 *msg += "...";
943 break;
944 default:
945 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
946 }
947 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700948 /*
949 * Verify that "array" is non-NULL and points to an Array object.
950 *
951 * Since we're dealing with objects, switch to "running" mode.
952 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700953 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
954 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
955 if (UNLIKELY(java_array == nullptr)) {
956 AbortF("jarray was NULL");
957 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700958 }
959
Ian Rogers68d8b422014-07-17 11:09:10 -0700960 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
961 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700962 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700963 AbortF("jarray is an invalid %s: %p (%p)",
964 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
965 java_array, a);
966 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700967 } else if (!a->IsArrayInstance()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700968 AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
969 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700970 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700971 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700972 }
973
Ian Rogers68d8b422014-07-17 11:09:10 -0700974 bool CheckBoolean(jboolean z) {
975 if (z != JNI_TRUE && z != JNI_FALSE) {
976 AbortF("unexpected jboolean value: %d", z);
977 return false;
978 }
979 return true;
980 }
981
982 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700983 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700984 AbortF("negative jsize: %d", length);
985 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700986 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700987 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700988 }
989
Ian Rogers68d8b422014-07-17 11:09:10 -0700990 mirror::ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
991 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800992 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700993 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -0800994 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700995 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700996 mirror::ArtField* f = soa.DecodeField(fid);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700997 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700998 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700999 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001000 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001001 }
1002 return f;
1003 }
1004
Ian Rogers68d8b422014-07-17 11:09:10 -07001005 mirror::ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
1006 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001007 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001008 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001009 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001010 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001011 mirror::ArtMethod* m = soa.DecodeMethod(mid);
Mathieu Chartier590fee92013-09-13 13:46:47 -07001012 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -07001013 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001014 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001015 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001016 }
1017 return m;
1018 }
1019
Ian Rogers68d8b422014-07-17 11:09:10 -07001020 bool CheckThread(JNIEnv* env) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001021 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001022 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001023 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1024 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001025 }
1026
1027 // Get the *correct* JNIEnv by going through our TLS pointer.
1028 JNIEnvExt* threadEnv = self->GetJniEnv();
1029
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001030 // Verify that the current thread is (a) attached and (b) associated with
1031 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001032 if (env != threadEnv) {
1033 AbortF("thread %s using JNIEnv* from thread %s",
1034 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
1035 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001036 }
1037
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001038 // Verify that, if this thread previously made a critical "get" call, we
1039 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001040 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001041 case kFlag_CritOkay: // okay to call this method
1042 break;
1043 case kFlag_CritBad: // not okay to call
1044 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001045 AbortF("thread %s using JNI after critical get",
1046 ToStr<Thread>(*self).c_str());
1047 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001048 }
1049 break;
1050 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001051 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001052 threadEnv->critical++;
1053 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001054 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001055 threadEnv->critical--;
1056 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001057 AbortF("thread %s called too many critical releases",
1058 ToStr<Thread>(*self).c_str());
1059 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001060 }
1061 break;
1062 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001063 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001064 }
1065
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001066 // Verify that, if an exception has been raised, the native code doesn't
1067 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001068 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001069 ThrowLocation throw_location;
1070 mirror::Throwable* exception = self->GetException(&throw_location);
1071 std::string type(PrettyTypeOf(exception));
Ian Rogers68d8b422014-07-17 11:09:10 -07001072 AbortF("JNI %s called with pending exception '%s' thrown in %s",
1073 function_name_, type.c_str(), throw_location.Dump().c_str());
1074 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001075 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001076 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001077 }
1078
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001079 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001080 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001081 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001082 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001083 AbortF("non-nullable const char* was NULL");
1084 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001085 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001086 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001087 }
1088
Ian Rogersef7d42f2014-01-06 12:55:46 -08001089 const char* errorKind = nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001090 uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001091 if (errorKind != nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001092 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1093 " string: '%s'", errorKind, utf8, bytes);
1094 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001095 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001096 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001097 }
1098
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001099 static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001100 while (*bytes != '\0') {
1101 uint8_t utf8 = *(bytes++);
1102 // Switch on the high four bits.
1103 switch (utf8 >> 4) {
1104 case 0x00:
1105 case 0x01:
1106 case 0x02:
1107 case 0x03:
1108 case 0x04:
1109 case 0x05:
1110 case 0x06:
1111 case 0x07:
1112 // Bit pattern 0xxx. No need for any extra bytes.
1113 break;
1114 case 0x08:
1115 case 0x09:
1116 case 0x0a:
1117 case 0x0b:
1118 case 0x0f:
1119 /*
1120 * Bit pattern 10xx or 1111, which are illegal start bytes.
1121 * Note: 1111 is valid for normal UTF-8, but not the
Elliott Hughes78090d12011-10-07 14:31:47 -07001122 * Modified UTF-8 used here.
Elliott Hughesa2501992011-08-26 19:39:54 -07001123 */
1124 *errorKind = "start";
1125 return utf8;
1126 case 0x0e:
1127 // Bit pattern 1110, so there are two additional bytes.
1128 utf8 = *(bytes++);
1129 if ((utf8 & 0xc0) != 0x80) {
1130 *errorKind = "continuation";
1131 return utf8;
1132 }
Ian Rogersfc787ec2014-10-09 21:56:44 -07001133 FALLTHROUGH_INTENDED; // Fall-through to take care of the final byte.
Elliott Hughesa2501992011-08-26 19:39:54 -07001134 case 0x0c:
1135 case 0x0d:
1136 // Bit pattern 110x, so there is one additional byte.
1137 utf8 = *(bytes++);
1138 if ((utf8 & 0xc0) != 0x80) {
1139 *errorKind = "continuation";
1140 return utf8;
1141 }
1142 break;
1143 }
1144 }
1145 return 0;
1146 }
1147
Ian Rogers68d8b422014-07-17 11:09:10 -07001148 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1149 va_list args;
1150 va_start(args, fmt);
1151 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1152 va_end(args);
1153 }
1154
1155 // The name of the JNI function being checked.
1156 const char* const function_name_;
1157
1158 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001159 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001160
Ian Rogers68d8b422014-07-17 11:09:10 -07001161 const bool has_method_;
1162
Elliott Hughesa2501992011-08-26 19:39:54 -07001163 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1164};
1165
Elliott Hughesa2501992011-08-26 19:39:54 -07001166/*
1167 * ===========================================================================
1168 * Guarded arrays
1169 * ===========================================================================
1170 */
1171
Elliott Hughesa2501992011-08-26 19:39:54 -07001172/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001173class GuardedCopy {
1174 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001175 /*
1176 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1177 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001178 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001179 static void* Create(const void* original_buf, size_t len, bool mod_okay) {
1180 const size_t new_len = LengthIncludingRedZones(len);
1181 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001182
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001183 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001184 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001185 if (!mod_okay) {
1186 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001187 }
1188
Ian Rogers68d8b422014-07-17 11:09:10 -07001189 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001190
Ian Rogers68d8b422014-07-17 11:09:10 -07001191 // Fill begin region with canary pattern.
1192 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1193 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1194 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1195 if (kCanary[j] == '\0') {
1196 j = 0;
1197 }
1198 }
1199
1200 // Copy the data in; note "len" could be zero.
1201 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1202
1203 // Fill end region with canary pattern.
1204 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1205 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1206 if (kCanary[j] == '\0') {
1207 j = 0;
1208 }
1209 }
1210
1211 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001212 }
1213
1214 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001215 * Create a guarded copy of a primitive array. Modifications to the copied
1216 * data are allowed. Returns a pointer to the copied data.
1217 */
1218 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy) {
1219 ScopedObjectAccess soa(env);
1220
1221 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1222 size_t component_size = a->GetClass()->GetComponentSize();
1223 size_t byte_count = a->GetLength() * component_size;
1224 void* result = Create(a->GetRawData(component_size, 0), byte_count, true);
1225 if (is_copy != nullptr) {
1226 *is_copy = JNI_TRUE;
1227 }
1228 return result;
1229 }
1230
1231 /*
1232 * Perform the array "release" operation, which may or may not copy data
1233 * back into the managed heap, and may or may not release the underlying storage.
1234 */
1235 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, jarray java_array,
1236 void* embedded_buf, int mode) {
1237 ScopedObjectAccess soa(env);
1238 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1239
1240 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1241 return nullptr;
1242 }
1243 if (mode != JNI_ABORT) {
1244 size_t len = FromEmbedded(embedded_buf)->original_length_;
1245 memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), embedded_buf, len);
1246 }
1247 if (mode != JNI_COMMIT) {
1248 return Destroy(embedded_buf);
1249 }
1250 return embedded_buf;
1251 }
1252
1253
1254 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001255 * Free up the guard buffer, scrub it, and return the original pointer.
1256 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001257 static void* Destroy(void* embedded_buf) {
1258 GuardedCopy* copy = FromEmbedded(embedded_buf);
1259 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1260 size_t len = LengthIncludingRedZones(copy->original_length_);
1261 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001262 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001263 }
1264
1265 /*
1266 * Verify the guard area and, if "modOkay" is false, that the data itself
1267 * has not been altered.
1268 *
1269 * The caller has already checked that "dataBuf" is non-NULL.
1270 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001271 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1272 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1273 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001274 }
1275
1276 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07001277 GuardedCopy(const void* original_buf, size_t len, uLong adler) :
1278 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1279 }
1280
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001281 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001282 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001283 if (result == MAP_FAILED) {
1284 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1285 }
1286 return reinterpret_cast<uint8_t*>(result);
1287 }
1288
Ian Rogers68d8b422014-07-17 11:09:10 -07001289 static void DebugFree(void* buf, size_t len) {
1290 if (munmap(buf, len) != 0) {
1291 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001292 }
1293 }
1294
Ian Rogers68d8b422014-07-17 11:09:10 -07001295 static size_t LengthIncludingRedZones(size_t len) {
1296 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001297 }
1298
Ian Rogers68d8b422014-07-17 11:09:10 -07001299 // Get the GuardedCopy from the interior pointer.
1300 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1301 return reinterpret_cast<GuardedCopy*>(
1302 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001303 }
1304
Ian Rogers68d8b422014-07-17 11:09:10 -07001305 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1306 return reinterpret_cast<const GuardedCopy*>(
1307 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001308 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001309
1310 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1311 va_list args;
1312 va_start(args, fmt);
1313 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1314 va_end(args);
1315 }
1316
1317 bool CheckHeader(const char* function_name, bool mod_okay) const {
1318 static const uint32_t kMagicCmp = kGuardMagic;
1319
1320 // Before we do anything with "pExtra", check the magic number. We
1321 // do the check with memcmp rather than "==" in case the pointer is
1322 // unaligned. If it points to completely bogus memory we're going
1323 // to crash, but there's no easy way around that.
1324 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1325 uint8_t buf[4];
1326 memcpy(buf, &magic_, 4);
1327 AbortF(function_name,
1328 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1329 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1330 return false;
1331 }
1332
1333 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1334 // told the client that we made a copy, there's no reason they can't alter the buffer.
1335 if (!mod_okay) {
1336 uLong computed_adler =
1337 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1338 if (computed_adler != adler_) {
1339 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1340 computed_adler, adler_, this);
1341 return false;
1342 }
1343 }
1344 return true;
1345 }
1346
1347 bool CheckRedZones(const char* function_name) const {
1348 // Check the begin red zone.
1349 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1350 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1351 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1352 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1353 return false;
1354 }
1355 if (kCanary[j] == '\0') {
1356 j = 0;
1357 }
1358 }
1359
1360 // Check end region.
1361 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1362 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1363 size_t offset_from_buffer_start =
1364 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1365 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1366 offset_from_buffer_start);
1367 return false;
1368 }
1369 if (kCanary[j] == '\0') {
1370 j = 0;
1371 }
1372 }
1373 return true;
1374 }
1375
1376 // Location that canary value will be written before the guarded region.
1377 const char* StartRedZone() const {
1378 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1379 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1380 }
1381
1382 // Return the interior embedded buffer.
1383 const uint8_t* BufferWithinRedZones() const {
1384 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1385 return embedded_buf;
1386 }
1387
1388 // Location that canary value will be written after the guarded region.
1389 const char* EndRedZone() const {
1390 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1391 size_t buf_len = LengthIncludingRedZones(original_length_);
1392 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1393 }
1394
1395 static constexpr size_t kRedZoneSize = 512;
1396 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1397
1398 // Value written before and after the guarded array.
1399 static const char* const kCanary;
1400
1401 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1402
1403 const uint32_t magic_;
1404 const uLong adler_;
1405 const void* const original_ptr_;
1406 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001407};
Ian Rogers68d8b422014-07-17 11:09:10 -07001408const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001409
1410/*
1411 * ===========================================================================
1412 * JNI functions
1413 * ===========================================================================
1414 */
1415
1416class CheckJNI {
1417 public:
1418 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001419 ScopedObjectAccess soa(env);
1420 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1421 JniValueType args[1] = {{.E = env }};
1422 if (sc.Check(soa, true, "E", args)) {
1423 JniValueType result;
1424 result.I = baseEnv(env)->GetVersion(env);
1425 if (sc.Check(soa, false, "I", &result)) {
1426 return result.I;
1427 }
1428 }
1429 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001430 }
1431
Ian Rogers68d8b422014-07-17 11:09:10 -07001432 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1433 ScopedObjectAccess soa(env);
1434 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1435 JniValueType args[2] = {{.E = env }, {.p = vm}};
1436 if (sc.Check(soa, true, "Ep", args)) {
1437 JniValueType result;
1438 result.i = baseEnv(env)->GetJavaVM(env, vm);
1439 if (sc.Check(soa, false, "i", &result)) {
1440 return result.i;
1441 }
1442 }
1443 return JNI_ERR;
1444 }
1445
1446 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1447 ScopedObjectAccess soa(env);
1448 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1449 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1450 if (sc.Check(soa, true, "EcpI", args)) {
1451 JniValueType result;
1452 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1453 if (sc.Check(soa, false, "i", &result)) {
1454 return result.i;
1455 }
1456 }
1457 return JNI_ERR;
1458 }
1459
1460 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1461 ScopedObjectAccess soa(env);
1462 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1463 JniValueType args[2] = {{.E = env }, {.c = c}};
1464 if (sc.Check(soa, true, "Ec", args)) {
1465 JniValueType result;
1466 result.i = baseEnv(env)->UnregisterNatives(env, c);
1467 if (sc.Check(soa, false, "i", &result)) {
1468 return result.i;
1469 }
1470 }
1471 return JNI_ERR;
1472 }
1473
1474 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001475 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1476 // know the object is invalid. The spec says that passing invalid objects or even ones that
1477 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001478 ScopedObjectAccess soa(env);
1479 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001480 JniValueType args[2] = {{.E = env }, {.L = obj}};
1481 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001482 JniValueType result;
1483 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1484 if (sc.Check(soa, false, "w", &result)) {
1485 return result.w;
1486 }
1487 }
1488 return JNIInvalidRefType;
1489 }
1490
1491 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1492 jsize bufLen) {
1493 ScopedObjectAccess soa(env);
1494 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1495 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1496 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1497 JniValueType result;
1498 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1499 if (sc.Check(soa, false, "c", &result)) {
1500 return result.c;
1501 }
1502 }
1503 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001504 }
1505
1506 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001507 ScopedObjectAccess soa(env);
1508 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1509 JniValueType args[2] = {{.E = env}, {.u = name}};
1510 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1511 JniValueType result;
1512 result.c = baseEnv(env)->FindClass(env, name);
1513 if (sc.Check(soa, false, "c", &result)) {
1514 return result.c;
1515 }
1516 }
1517 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001518 }
1519
Elliott Hughese84278b2012-03-22 10:06:53 -07001520 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001521 ScopedObjectAccess soa(env);
1522 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1523 JniValueType args[2] = {{.E = env}, {.c = c}};
1524 if (sc.Check(soa, true, "Ec", args)) {
1525 JniValueType result;
1526 result.c = baseEnv(env)->GetSuperclass(env, c);
1527 if (sc.Check(soa, false, "c", &result)) {
1528 return result.c;
1529 }
1530 }
1531 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001532 }
1533
Elliott Hughese84278b2012-03-22 10:06:53 -07001534 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001535 ScopedObjectAccess soa(env);
1536 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1537 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1538 if (sc.Check(soa, true, "Ecc", args)) {
1539 JniValueType result;
1540 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1541 if (sc.Check(soa, false, "b", &result)) {
1542 return result.b;
1543 }
1544 }
1545 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001546 }
1547
1548 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001549 ScopedObjectAccess soa(env);
1550 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1551 JniValueType args[2] = {{.E = env}, {.L = method}};
1552 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1553 JniValueType result;
1554 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1555 if (sc.Check(soa, false, "m", &result)) {
1556 return result.m;
1557 }
1558 }
1559 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001560 }
1561
1562 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001563 ScopedObjectAccess soa(env);
1564 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1565 JniValueType args[2] = {{.E = env}, {.L = field}};
1566 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1567 JniValueType result;
1568 result.f = baseEnv(env)->FromReflectedField(env, field);
1569 if (sc.Check(soa, false, "f", &result)) {
1570 return result.f;
1571 }
1572 }
1573 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001574 }
1575
1576 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001577 ScopedObjectAccess soa(env);
1578 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1579 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1580 if (sc.Check(soa, true, "Ecmb", args)) {
1581 JniValueType result;
1582 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1583 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1584 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1585 return result.L;
1586 }
1587 }
1588 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001589 }
1590
1591 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001592 ScopedObjectAccess soa(env);
1593 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1594 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1595 if (sc.Check(soa, true, "Ecfb", args)) {
1596 JniValueType result;
1597 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1598 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1599 DCHECK(sc.CheckReflectedField(soa, result.L));
1600 return result.L;
1601 }
1602 }
1603 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001604 }
1605
1606 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001607 ScopedObjectAccess soa(env);
1608 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1609 JniValueType args[2] = {{.E = env}, {.t = obj}};
1610 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1611 JniValueType result;
1612 result.i = baseEnv(env)->Throw(env, obj);
1613 if (sc.Check(soa, false, "i", &result)) {
1614 return result.i;
1615 }
1616 }
1617 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001618 }
1619
Elliott Hughese84278b2012-03-22 10:06:53 -07001620 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001621 ScopedObjectAccess soa(env);
1622 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
1623 JniValueType args[5] = {{.E = env}, {.c = c}, {.u = message}};
1624 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1625 JniValueType result;
1626 result.i = baseEnv(env)->ThrowNew(env, c, message);
1627 if (sc.Check(soa, false, "i", &result)) {
1628 return result.i;
1629 }
1630 }
1631 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001632 }
1633
1634 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001635 ScopedObjectAccess soa(env);
1636 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1637 JniValueType args[1] = {{.E = env}};
1638 if (sc.Check(soa, true, "E", args)) {
1639 JniValueType result;
1640 result.t = baseEnv(env)->ExceptionOccurred(env);
1641 if (sc.Check(soa, false, "t", &result)) {
1642 return result.t;
1643 }
1644 }
1645 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001646 }
1647
1648 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001649 ScopedObjectAccess soa(env);
1650 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1651 JniValueType args[1] = {{.E = env}};
1652 if (sc.Check(soa, true, "E", args)) {
1653 JniValueType result;
1654 baseEnv(env)->ExceptionDescribe(env);
1655 result.V = nullptr;
1656 sc.Check(soa, false, "V", &result);
1657 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001658 }
1659
1660 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001661 ScopedObjectAccess soa(env);
1662 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1663 JniValueType args[1] = {{.E = env}};
1664 if (sc.Check(soa, true, "E", args)) {
1665 JniValueType result;
1666 baseEnv(env)->ExceptionClear(env);
1667 result.V = nullptr;
1668 sc.Check(soa, false, "V", &result);
1669 }
1670 }
1671
1672 static jboolean ExceptionCheck(JNIEnv* env) {
1673 ScopedObjectAccess soa(env);
1674 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1675 JniValueType args[1] = {{.E = env}};
1676 if (sc.Check(soa, true, "E", args)) {
1677 JniValueType result;
1678 result.b = baseEnv(env)->ExceptionCheck(env);
1679 if (sc.Check(soa, false, "b", &result)) {
1680 return result.b;
1681 }
1682 }
1683 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001684 }
1685
1686 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001687 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1688 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1689 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001690 ScopedObjectAccess soa(env);
1691 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1692 JniValueType args[2] = {{.E = env}, {.u = msg}};
1693 if (sc.Check(soa, true, "Eu", args)) {
1694 JniValueType result;
1695 baseEnv(env)->FatalError(env, msg);
1696 // Unreachable.
1697 result.V = nullptr;
1698 sc.Check(soa, false, "V", &result);
1699 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001700 }
1701
1702 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001703 ScopedObjectAccess soa(env);
1704 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1705 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1706 if (sc.Check(soa, true, "EI", args)) {
1707 JniValueType result;
1708 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1709 if (sc.Check(soa, false, "i", &result)) {
1710 return result.i;
1711 }
1712 }
1713 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001714 }
1715
1716 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001717 ScopedObjectAccess soa(env);
1718 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1719 JniValueType args[2] = {{.E = env}, {.L = res}};
1720 if (sc.Check(soa, true, "EL", args)) {
1721 JniValueType result;
1722 result.L = baseEnv(env)->PopLocalFrame(env, res);
1723 sc.Check(soa, false, "L", &result);
1724 return result.L;
1725 }
1726 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001727 }
1728
1729 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001730 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001731 }
1732
Ian Rogers68d8b422014-07-17 11:09:10 -07001733 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1734 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001735 }
1736
1737 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001738 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001739 }
1740
Ian Rogers68d8b422014-07-17 11:09:10 -07001741 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1742 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001743 }
1744
Ian Rogers68d8b422014-07-17 11:09:10 -07001745 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1746 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1747 }
1748
1749 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1750 DeleteRef(__FUNCTION__, env, obj, kLocal);
1751 }
1752
1753 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1754 ScopedObjectAccess soa(env);
1755 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1756 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1757 if (sc.Check(soa, true, "EI", args)) {
1758 JniValueType result;
1759 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1760 if (sc.Check(soa, false, "i", &result)) {
1761 return result.i;
1762 }
1763 }
1764 return JNI_ERR;
1765 }
1766
1767 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1768 ScopedObjectAccess soa(env);
1769 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1770 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1771 if (sc.Check(soa, true, "ELL", args)) {
1772 JniValueType result;
1773 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1774 if (sc.Check(soa, false, "b", &result)) {
1775 return result.b;
1776 }
1777 }
1778 return JNI_FALSE;
1779 }
1780
1781 static jobject AllocObject(JNIEnv* env, jclass c) {
1782 ScopedObjectAccess soa(env);
1783 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1784 JniValueType args[2] = {{.E = env}, {.c = c}};
1785 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1786 JniValueType result;
1787 result.L = baseEnv(env)->AllocObject(env, c);
1788 if (sc.Check(soa, false, "L", &result)) {
1789 return result.L;
1790 }
1791 }
1792 return nullptr;
1793 }
1794
1795 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1796 ScopedObjectAccess soa(env);
1797 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1798 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
1799 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
1800 sc.CheckConstructor(soa, mid)) {
1801 JniValueType result;
1802 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
1803 if (sc.Check(soa, false, "L", &result)) {
1804 return result.L;
1805 }
1806 }
1807 return nullptr;
1808 }
1809
1810 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1811 va_list args;
1812 va_start(args, mid);
1813 jobject result = NewObjectV(env, c, mid, args);
1814 va_end(args);
1815 return result;
1816 }
1817
1818 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
1819 ScopedObjectAccess soa(env);
1820 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1821 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
1822 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
1823 sc.CheckConstructor(soa, mid)) {
1824 JniValueType result;
1825 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
1826 if (sc.Check(soa, false, "L", &result)) {
1827 return result.L;
1828 }
1829 }
1830 return nullptr;
1831 }
1832
1833 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1834 ScopedObjectAccess soa(env);
1835 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1836 JniValueType args[2] = {{.E = env}, {.L = obj}};
1837 if (sc.Check(soa, true, "EL", args)) {
1838 JniValueType result;
1839 result.c = baseEnv(env)->GetObjectClass(env, obj);
1840 if (sc.Check(soa, false, "c", &result)) {
1841 return result.c;
1842 }
1843 }
1844 return nullptr;
1845 }
1846
1847 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1848 ScopedObjectAccess soa(env);
1849 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1850 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
1851 if (sc.Check(soa, true, "ELc", args)) {
1852 JniValueType result;
1853 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
1854 if (sc.Check(soa, false, "b", &result)) {
1855 return result.b;
1856 }
1857 }
1858 return JNI_FALSE;
1859 }
1860
1861 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1862 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
1863 }
1864
1865 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1866 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
1867 }
1868
1869 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1870 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
1871 }
1872
1873 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1874 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
1875 }
1876
1877#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
1878 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1879 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
1880 } \
1881 \
1882 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1883 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
1884 } \
1885 \
1886 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
1887 JniValueType value; \
1888 value.shorty = v; \
1889 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
1890 } \
1891 \
1892 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
1893 JniValueType value; \
1894 value.shorty = v; \
1895 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
1896 }
1897
1898 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
1899 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
1900 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
1901 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
1902 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
1903 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
1904 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
1905 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
1906 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
1907#undef FIELD_ACCESSORS
1908
1909 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
1910 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1911 }
1912
1913 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1914 jvalue* vargs) {
1915 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1916 }
1917
1918 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01001919 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07001920 }
1921
1922 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
1923 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1924 }
1925
1926 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1927 va_list vargs) {
1928 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1929 }
1930
1931 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1932 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1933 }
1934
1935 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1936 va_list vargs;
1937 va_start(vargs, mid);
1938 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1939 va_end(vargs);
1940 }
1941
1942 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
1943 va_list vargs;
1944 va_start(vargs, mid);
1945 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1946 va_end(vargs);
1947 }
1948
1949 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
1950 va_list vargs;
1951 va_start(vargs, mid);
1952 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1953 va_end(vargs);
1954 }
1955
1956#define CALL(rtype, name, ptype, shorty) \
1957 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
1958 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1959 } \
1960 \
1961 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1962 jvalue* vargs) { \
1963 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1964 } \
1965 \
1966 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
1967 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1968 } \
1969 \
1970 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
1971 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1972 } \
1973 \
1974 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1975 va_list vargs) { \
1976 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1977 } \
1978 \
1979 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
1980 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1981 } \
1982 \
1983 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
1984 va_list vargs; \
1985 va_start(vargs, mid); \
1986 rtype result = \
1987 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1988 va_end(vargs); \
1989 return result; \
1990 } \
1991 \
1992 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1993 ...) { \
1994 va_list vargs; \
1995 va_start(vargs, mid); \
1996 rtype result = \
1997 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1998 va_end(vargs); \
1999 return result; \
2000 } \
2001 \
2002 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2003 va_list vargs; \
2004 va_start(vargs, mid); \
2005 rtype result = \
2006 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2007 va_end(vargs); \
2008 return result; \
2009 }
2010
2011 CALL(jobject, Object, Primitive::kPrimNot, L)
2012 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2013 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2014 CALL(jchar, Char, Primitive::kPrimChar, C)
2015 CALL(jshort, Short, Primitive::kPrimShort, S)
2016 CALL(jint, Int, Primitive::kPrimInt, I)
2017 CALL(jlong, Long, Primitive::kPrimLong, J)
2018 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2019 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2020#undef CALL
2021
2022 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2023 ScopedObjectAccess soa(env);
2024 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2025 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2026 if (sc.Check(soa, true, "Epz", args)) {
2027 JniValueType result;
2028 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2029 if (sc.Check(soa, false, "s", &result)) {
2030 return result.s;
2031 }
2032 }
2033 return nullptr;
2034 }
2035
2036 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2037 ScopedObjectAccess soa(env);
2038 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2039 JniValueType args[2] = {{.E = env}, {.u = chars}};
2040 if (sc.Check(soa, true, "Eu", args)) {
2041 JniValueType result;
2042 // TODO: stale? show pointer and truncate string.
2043 result.s = baseEnv(env)->NewStringUTF(env, chars);
2044 if (sc.Check(soa, false, "s", &result)) {
2045 return result.s;
2046 }
2047 }
2048 return nullptr;
2049 }
2050
2051 static jsize GetStringLength(JNIEnv* env, jstring string) {
2052 ScopedObjectAccess soa(env);
2053 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2054 JniValueType args[2] = {{.E = env}, {.s = string}};
2055 if (sc.Check(soa, true, "Es", args)) {
2056 JniValueType result;
2057 result.z = baseEnv(env)->GetStringLength(env, string);
2058 if (sc.Check(soa, false, "z", &result)) {
2059 return result.z;
2060 }
2061 }
2062 return JNI_ERR;
2063 }
2064
2065 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2066 ScopedObjectAccess soa(env);
2067 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2068 JniValueType args[2] = {{.E = env}, {.s = string}};
2069 if (sc.Check(soa, true, "Es", args)) {
2070 JniValueType result;
2071 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2072 if (sc.Check(soa, false, "z", &result)) {
2073 return result.z;
2074 }
2075 }
2076 return JNI_ERR;
2077 }
2078
2079 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2080 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2081 is_copy, false, false));
2082 }
2083
2084 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2085 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2086 is_copy, true, false));
2087 }
2088
2089 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2090 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2091 is_copy, false, true));
2092 }
2093
2094 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2095 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2096 }
2097
2098 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2099 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2100 }
2101
2102 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2103 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2104 }
2105
2106 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2107 ScopedObjectAccess soa(env);
2108 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2109 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2110 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2111 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2112 if (sc.Check(soa, true, "EsIIp", args)) {
2113 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2114 JniValueType result;
2115 result.V = nullptr;
2116 sc.Check(soa, false, "V", &result);
2117 }
2118 }
2119
2120 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2121 ScopedObjectAccess soa(env);
2122 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2123 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2124 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2125 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2126 if (sc.Check(soa, true, "EsIIp", args)) {
2127 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2128 JniValueType result;
2129 result.V = nullptr;
2130 sc.Check(soa, false, "V", &result);
2131 }
2132 }
2133
2134 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2135 ScopedObjectAccess soa(env);
2136 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2137 JniValueType args[2] = {{.E = env}, {.a = array}};
2138 if (sc.Check(soa, true, "Ea", args)) {
2139 JniValueType result;
2140 result.z = baseEnv(env)->GetArrayLength(env, array);
2141 if (sc.Check(soa, false, "z", &result)) {
2142 return result.z;
2143 }
2144 }
2145 return JNI_ERR;
2146 }
2147
2148 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2149 jobject initial_element) {
2150 ScopedObjectAccess soa(env);
2151 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2152 JniValueType args[4] =
2153 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2154 if (sc.Check(soa, true, "EzcL", args)) {
2155 JniValueType result;
2156 // Note: assignability tests of initial_element are done in the base implementation.
2157 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2158 if (sc.Check(soa, false, "a", &result)) {
2159 return down_cast<jobjectArray>(result.a);
2160 }
2161 }
2162 return nullptr;
2163 }
2164
2165 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2166 ScopedObjectAccess soa(env);
2167 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2168 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2169 if (sc.Check(soa, true, "Eaz", args)) {
2170 JniValueType result;
2171 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2172 if (sc.Check(soa, false, "L", &result)) {
2173 return result.L;
2174 }
2175 }
2176 return nullptr;
2177 }
2178
2179 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2180 ScopedObjectAccess soa(env);
2181 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2182 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2183 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2184 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2185 // in ArrayStoreExceptions.
2186 if (sc.Check(soa, true, "EaIL", args)) {
2187 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2188 JniValueType result;
2189 result.V = nullptr;
2190 sc.Check(soa, false, "V", &result);
2191 }
2192 }
2193
2194 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2195 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2196 Primitive::kPrimBoolean));
2197 }
2198
2199 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2200 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2201 Primitive::kPrimByte));
2202 }
2203
2204 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2205 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2206 Primitive::kPrimChar));
2207 }
2208
2209 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2210 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2211 Primitive::kPrimShort));
2212 }
2213
2214 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2215 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2216 }
2217
2218 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2219 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2220 Primitive::kPrimLong));
2221 }
2222
2223 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2224 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2225 Primitive::kPrimFloat));
2226 }
2227
2228 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2229 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2230 Primitive::kPrimDouble));
2231 }
2232
2233#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2234 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
2235 return reinterpret_cast<ctype*>( \
2236 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2237 } \
2238 \
2239 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
2240 jint mode) { \
2241 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2242 } \
2243 \
2244 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2245 ctype* buf) { \
2246 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2247 } \
2248 \
2249 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2250 const ctype* buf) { \
2251 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2252 }
2253
2254 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2255 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2256 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2257 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2258 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2259 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2260 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2261 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2262#undef PRIMITIVE_ARRAY_FUNCTIONS
2263
2264 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2265 ScopedObjectAccess soa(env);
2266 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2267 JniValueType args[2] = {{.E = env}, {.L = obj}};
2268 if (sc.Check(soa, true, "EL", args)) {
2269 JniValueType result;
2270 result.i = baseEnv(env)->MonitorEnter(env, obj);
2271 if (sc.Check(soa, false, "i", &result)) {
2272 return result.i;
2273 }
2274 }
2275 return JNI_ERR;
2276 }
2277
2278 static jint MonitorExit(JNIEnv* env, jobject obj) {
2279 ScopedObjectAccess soa(env);
2280 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2281 JniValueType args[2] = {{.E = env}, {.L = obj}};
2282 if (sc.Check(soa, true, "EL", args)) {
2283 JniValueType result;
2284 result.i = baseEnv(env)->MonitorExit(env, obj);
2285 if (sc.Check(soa, false, "i", &result)) {
2286 return result.i;
2287 }
2288 }
2289 return JNI_ERR;
2290 }
2291
2292 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2293 ScopedObjectAccess soa(env);
2294 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2295 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2296 if (sc.Check(soa, true, "Eap", args)) {
2297 JniValueType result;
2298 result.p = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2299 if (result.p != nullptr && soa.ForceCopy()) {
2300 result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
2301 }
2302 if (sc.Check(soa, false, "p", &result)) {
2303 return const_cast<void*>(result.p);
2304 }
2305 }
2306 return nullptr;
2307 }
2308
2309 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2310 ScopedObjectAccess soa(env);
2311 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2312 sc.CheckNonNull(carray);
2313 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2314 if (sc.Check(soa, true, "Eapr", args)) {
2315 if (soa.ForceCopy()) {
2316 GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
2317 }
2318 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2319 JniValueType result;
2320 result.V = nullptr;
2321 sc.Check(soa, false, "V", &result);
2322 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002323 }
2324
2325 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002326 ScopedObjectAccess soa(env);
2327 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2328 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2329 if (sc.Check(soa, true, "EpJ", args)) {
2330 JniValueType result;
2331 // Note: the validity of address and capacity are checked in the base implementation.
2332 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2333 if (sc.Check(soa, false, "L", &result)) {
2334 return result.L;
2335 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002336 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002337 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002338 }
2339
2340 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002341 ScopedObjectAccess soa(env);
2342 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2343 JniValueType args[2] = {{.E = env}, {.L = buf}};
2344 if (sc.Check(soa, true, "EL", args)) {
2345 JniValueType result;
2346 // Note: this is implemented in the base environment by a GetLongField which will sanity
2347 // check the type of buf in GetLongField above.
2348 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2349 if (sc.Check(soa, false, "p", &result)) {
2350 return const_cast<void*>(result.p);
2351 }
2352 }
2353 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002354 }
2355
2356 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002357 ScopedObjectAccess soa(env);
2358 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2359 JniValueType args[2] = {{.E = env}, {.L = buf}};
2360 if (sc.Check(soa, true, "EL", args)) {
2361 JniValueType result;
2362 // Note: this is implemented in the base environment by a GetIntField which will sanity
2363 // check the type of buf in GetIntField above.
2364 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2365 if (sc.Check(soa, false, "J", &result)) {
2366 return result.J;
2367 }
2368 }
2369 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002370 }
2371
2372 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002373 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2374 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2375 }
2376
2377 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002378 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2379 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002380
2381 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2382 ScopedObjectAccess soa(env);
2383 ScopedCheck sc(kFlag_Default, function_name);
2384 JniValueType args[2] = {{.E = env}, {.L = obj}};
2385 if (sc.Check(soa, true, "EL", args)) {
2386 JniValueType result;
2387 switch (kind) {
2388 case kGlobal:
2389 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2390 break;
2391 case kLocal:
2392 result.L = baseEnv(env)->NewLocalRef(env, obj);
2393 break;
2394 case kWeakGlobal:
2395 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2396 break;
2397 default:
2398 LOG(FATAL) << "Unexpected reference kind: " << kind;
2399 }
2400 if (sc.Check(soa, false, "L", &result)) {
2401 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002402 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002403 return result.L;
2404 }
2405 }
2406 return nullptr;
2407 }
2408
2409 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2410 ScopedObjectAccess soa(env);
2411 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2412 JniValueType args[2] = {{.E = env}, {.L = obj}};
2413 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002414 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002415 JniValueType result;
2416 switch (kind) {
2417 case kGlobal:
2418 baseEnv(env)->DeleteGlobalRef(env, obj);
2419 break;
2420 case kLocal:
2421 baseEnv(env)->DeleteLocalRef(env, obj);
2422 break;
2423 case kWeakGlobal:
2424 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2425 break;
2426 default:
2427 LOG(FATAL) << "Unexpected reference kind: " << kind;
2428 }
2429 result.V = nullptr;
2430 sc.Check(soa, false, "V", &result);
2431 }
2432 }
2433
2434 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2435 const char* name, const char* sig, bool is_static) {
2436 ScopedObjectAccess soa(env);
2437 ScopedCheck sc(kFlag_Default, function_name);
2438 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2439 if (sc.Check(soa, true, "Ecuu", args)) {
2440 JniValueType result;
2441 if (is_static) {
2442 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2443 } else {
2444 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2445 }
2446 if (sc.Check(soa, false, "m", &result)) {
2447 return result.m;
2448 }
2449 }
2450 return nullptr;
2451 }
2452
2453 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2454 const char* name, const char* sig, bool is_static) {
2455 ScopedObjectAccess soa(env);
2456 ScopedCheck sc(kFlag_Default, function_name);
2457 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2458 if (sc.Check(soa, true, "Ecuu", args)) {
2459 JniValueType result;
2460 if (is_static) {
2461 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2462 } else {
2463 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2464 }
2465 if (sc.Check(soa, false, "f", &result)) {
2466 return result.f;
2467 }
2468 }
2469 return nullptr;
2470 }
2471
2472 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2473 bool is_static, Primitive::Type type) {
2474 ScopedObjectAccess soa(env);
2475 ScopedCheck sc(kFlag_Default, function_name);
2476 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2477 JniValueType result;
2478 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2479 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2480 const char* result_check = nullptr;
2481 switch (type) {
2482 case Primitive::kPrimNot:
2483 if (is_static) {
2484 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2485 } else {
2486 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2487 }
2488 result_check = "L";
2489 break;
2490 case Primitive::kPrimBoolean:
2491 if (is_static) {
2492 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2493 } else {
2494 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2495 }
2496 result_check = "Z";
2497 break;
2498 case Primitive::kPrimByte:
2499 if (is_static) {
2500 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2501 } else {
2502 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2503 }
2504 result_check = "B";
2505 break;
2506 case Primitive::kPrimChar:
2507 if (is_static) {
2508 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2509 } else {
2510 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2511 }
2512 result_check = "C";
2513 break;
2514 case Primitive::kPrimShort:
2515 if (is_static) {
2516 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2517 } else {
2518 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2519 }
2520 result_check = "S";
2521 break;
2522 case Primitive::kPrimInt:
2523 if (is_static) {
2524 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2525 } else {
2526 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2527 }
2528 result_check = "I";
2529 break;
2530 case Primitive::kPrimLong:
2531 if (is_static) {
2532 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2533 } else {
2534 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2535 }
2536 result_check = "J";
2537 break;
2538 case Primitive::kPrimFloat:
2539 if (is_static) {
2540 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2541 } else {
2542 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2543 }
2544 result_check = "F";
2545 break;
2546 case Primitive::kPrimDouble:
2547 if (is_static) {
2548 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2549 } else {
2550 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2551 }
2552 result_check = "D";
2553 break;
2554 case Primitive::kPrimVoid:
2555 LOG(FATAL) << "Unexpected type: " << type;
2556 break;
2557 }
2558 if (sc.Check(soa, false, result_check, &result)) {
2559 return result;
2560 }
2561 }
2562 result.J = 0;
2563 return result;
2564 }
2565
2566 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2567 bool is_static, Primitive::Type type, JniValueType value) {
2568 ScopedObjectAccess soa(env);
2569 ScopedCheck sc(kFlag_Default, function_name);
2570 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2571 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2572 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2573 if (sc.Check(soa, true, sig, args) &&
2574 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2575 switch (type) {
2576 case Primitive::kPrimNot:
2577 if (is_static) {
2578 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2579 } else {
2580 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2581 }
2582 break;
2583 case Primitive::kPrimBoolean:
2584 if (is_static) {
2585 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2586 } else {
2587 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2588 }
2589 break;
2590 case Primitive::kPrimByte:
2591 if (is_static) {
2592 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2593 } else {
2594 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2595 }
2596 break;
2597 case Primitive::kPrimChar:
2598 if (is_static) {
2599 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2600 } else {
2601 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2602 }
2603 break;
2604 case Primitive::kPrimShort:
2605 if (is_static) {
2606 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2607 } else {
2608 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2609 }
2610 break;
2611 case Primitive::kPrimInt:
2612 if (is_static) {
2613 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2614 } else {
2615 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2616 }
2617 break;
2618 case Primitive::kPrimLong:
2619 if (is_static) {
2620 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2621 } else {
2622 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2623 }
2624 break;
2625 case Primitive::kPrimFloat:
2626 if (is_static) {
2627 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2628 } else {
2629 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2630 }
2631 break;
2632 case Primitive::kPrimDouble:
2633 if (is_static) {
2634 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2635 } else {
2636 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2637 }
2638 break;
2639 case Primitive::kPrimVoid:
2640 LOG(FATAL) << "Unexpected type: " << type;
2641 break;
2642 }
2643 JniValueType result;
2644 result.V = nullptr;
2645 sc.Check(soa, false, "V", &result);
2646 }
2647 }
2648
2649 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
2650 jclass c, jmethodID mid, InvokeType invoke)
2651 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2652 bool checked;
2653 switch (invoke) {
2654 case kVirtual: {
2655 DCHECK(c == nullptr);
2656 JniValueType args[3] = {{.E = env}, {.L = obj}, {.m = mid}};
2657 checked = sc.Check(soa, true, "ELm.", args);
2658 break;
2659 }
2660 case kDirect: {
2661 JniValueType args[4] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}};
2662 checked = sc.Check(soa, true, "ELcm.", args);
2663 break;
2664 }
2665 case kStatic: {
2666 DCHECK(obj == nullptr);
2667 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
2668 checked = sc.Check(soa, true, "Ecm.", args);
2669 break;
2670 }
2671 default:
2672 LOG(FATAL) << "Unexpected invoke: " << invoke;
2673 checked = false;
2674 break;
2675 }
2676 return checked;
2677 }
2678
2679 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2680 jmethodID mid, jvalue* vargs, Primitive::Type type,
2681 InvokeType invoke) {
2682 ScopedObjectAccess soa(env);
2683 ScopedCheck sc(kFlag_Default, function_name);
2684 JniValueType result;
2685 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2686 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2687 const char* result_check;
2688 switch (type) {
2689 case Primitive::kPrimNot:
2690 result_check = "L";
2691 switch (invoke) {
2692 case kVirtual:
2693 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2694 break;
2695 case kDirect:
2696 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2697 break;
2698 case kStatic:
2699 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2700 break;
2701 default:
2702 break;
2703 }
2704 break;
2705 case Primitive::kPrimBoolean:
2706 result_check = "Z";
2707 switch (invoke) {
2708 case kVirtual:
2709 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2710 break;
2711 case kDirect:
2712 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2713 break;
2714 case kStatic:
2715 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2716 break;
2717 default:
2718 break;
2719 }
2720 break;
2721 case Primitive::kPrimByte:
2722 result_check = "B";
2723 switch (invoke) {
2724 case kVirtual:
2725 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2726 break;
2727 case kDirect:
2728 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2729 break;
2730 case kStatic:
2731 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2732 break;
2733 default:
2734 break;
2735 }
2736 break;
2737 case Primitive::kPrimChar:
2738 result_check = "C";
2739 switch (invoke) {
2740 case kVirtual:
2741 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2742 break;
2743 case kDirect:
2744 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2745 break;
2746 case kStatic:
2747 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2748 break;
2749 default:
2750 break;
2751 }
2752 break;
2753 case Primitive::kPrimShort:
2754 result_check = "S";
2755 switch (invoke) {
2756 case kVirtual:
2757 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2758 break;
2759 case kDirect:
2760 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2761 break;
2762 case kStatic:
2763 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2764 break;
2765 default:
2766 break;
2767 }
2768 break;
2769 case Primitive::kPrimInt:
2770 result_check = "I";
2771 switch (invoke) {
2772 case kVirtual:
2773 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2774 break;
2775 case kDirect:
2776 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2777 break;
2778 case kStatic:
2779 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2780 break;
2781 default:
2782 break;
2783 }
2784 break;
2785 case Primitive::kPrimLong:
2786 result_check = "J";
2787 switch (invoke) {
2788 case kVirtual:
2789 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
2790 break;
2791 case kDirect:
2792 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
2793 break;
2794 case kStatic:
2795 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
2796 break;
2797 default:
2798 break;
2799 }
2800 break;
2801 case Primitive::kPrimFloat:
2802 result_check = "F";
2803 switch (invoke) {
2804 case kVirtual:
2805 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
2806 break;
2807 case kDirect:
2808 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
2809 break;
2810 case kStatic:
2811 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
2812 break;
2813 default:
2814 break;
2815 }
2816 break;
2817 case Primitive::kPrimDouble:
2818 result_check = "D";
2819 switch (invoke) {
2820 case kVirtual:
2821 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
2822 break;
2823 case kDirect:
2824 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
2825 break;
2826 case kStatic:
2827 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
2828 break;
2829 default:
2830 break;
2831 }
2832 break;
2833 case Primitive::kPrimVoid:
2834 result_check = "V";
2835 result.V = nullptr;
2836 switch (invoke) {
2837 case kVirtual:
2838 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
2839 break;
2840 case kDirect:
2841 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
2842 break;
2843 case kStatic:
2844 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
2845 break;
2846 default:
2847 LOG(FATAL) << "Unexpected invoke: " << invoke;
2848 }
2849 break;
2850 default:
2851 LOG(FATAL) << "Unexpected return type: " << type;
2852 result_check = nullptr;
2853 }
2854 if (sc.Check(soa, false, result_check, &result)) {
2855 return result;
2856 }
2857 }
2858 result.J = 0;
2859 return result;
2860 }
2861
2862 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2863 jmethodID mid, va_list vargs, Primitive::Type type,
2864 InvokeType invoke) {
2865 ScopedObjectAccess soa(env);
2866 ScopedCheck sc(kFlag_Default, function_name);
2867 JniValueType result;
2868 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2869 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2870 const char* result_check;
2871 switch (type) {
2872 case Primitive::kPrimNot:
2873 result_check = "L";
2874 switch (invoke) {
2875 case kVirtual:
2876 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
2877 break;
2878 case kDirect:
2879 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
2880 break;
2881 case kStatic:
2882 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
2883 break;
2884 default:
2885 LOG(FATAL) << "Unexpected invoke: " << invoke;
2886 }
2887 break;
2888 case Primitive::kPrimBoolean:
2889 result_check = "Z";
2890 switch (invoke) {
2891 case kVirtual:
2892 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
2893 break;
2894 case kDirect:
2895 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
2896 break;
2897 case kStatic:
2898 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
2899 break;
2900 default:
2901 LOG(FATAL) << "Unexpected invoke: " << invoke;
2902 }
2903 break;
2904 case Primitive::kPrimByte:
2905 result_check = "B";
2906 switch (invoke) {
2907 case kVirtual:
2908 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
2909 break;
2910 case kDirect:
2911 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
2912 break;
2913 case kStatic:
2914 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
2915 break;
2916 default:
2917 LOG(FATAL) << "Unexpected invoke: " << invoke;
2918 }
2919 break;
2920 case Primitive::kPrimChar:
2921 result_check = "C";
2922 switch (invoke) {
2923 case kVirtual:
2924 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
2925 break;
2926 case kDirect:
2927 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
2928 break;
2929 case kStatic:
2930 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
2931 break;
2932 default:
2933 LOG(FATAL) << "Unexpected invoke: " << invoke;
2934 }
2935 break;
2936 case Primitive::kPrimShort:
2937 result_check = "S";
2938 switch (invoke) {
2939 case kVirtual:
2940 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
2941 break;
2942 case kDirect:
2943 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
2944 break;
2945 case kStatic:
2946 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
2947 break;
2948 default:
2949 LOG(FATAL) << "Unexpected invoke: " << invoke;
2950 }
2951 break;
2952 case Primitive::kPrimInt:
2953 result_check = "I";
2954 switch (invoke) {
2955 case kVirtual:
2956 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
2957 break;
2958 case kDirect:
2959 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
2960 break;
2961 case kStatic:
2962 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
2963 break;
2964 default:
2965 LOG(FATAL) << "Unexpected invoke: " << invoke;
2966 }
2967 break;
2968 case Primitive::kPrimLong:
2969 result_check = "J";
2970 switch (invoke) {
2971 case kVirtual:
2972 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
2973 break;
2974 case kDirect:
2975 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
2976 break;
2977 case kStatic:
2978 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
2979 break;
2980 default:
2981 LOG(FATAL) << "Unexpected invoke: " << invoke;
2982 }
2983 break;
2984 case Primitive::kPrimFloat:
2985 result_check = "F";
2986 switch (invoke) {
2987 case kVirtual:
2988 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
2989 break;
2990 case kDirect:
2991 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
2992 break;
2993 case kStatic:
2994 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
2995 break;
2996 default:
2997 LOG(FATAL) << "Unexpected invoke: " << invoke;
2998 }
2999 break;
3000 case Primitive::kPrimDouble:
3001 result_check = "D";
3002 switch (invoke) {
3003 case kVirtual:
3004 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3005 break;
3006 case kDirect:
3007 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3008 break;
3009 case kStatic:
3010 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3011 break;
3012 default:
3013 LOG(FATAL) << "Unexpected invoke: " << invoke;
3014 }
3015 break;
3016 case Primitive::kPrimVoid:
3017 result_check = "V";
3018 result.V = nullptr;
3019 switch (invoke) {
3020 case kVirtual:
3021 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3022 break;
3023 case kDirect:
3024 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3025 break;
3026 case kStatic:
3027 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3028 break;
3029 default:
3030 LOG(FATAL) << "Unexpected invoke: " << invoke;
3031 }
3032 break;
3033 default:
3034 LOG(FATAL) << "Unexpected return type: " << type;
3035 result_check = nullptr;
3036 }
3037 if (sc.Check(soa, false, result_check, &result)) {
3038 return result;
3039 }
3040 }
3041 result.J = 0;
3042 return result;
3043 }
3044
3045 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3046 jboolean* is_copy, bool utf, bool critical) {
3047 ScopedObjectAccess soa(env);
3048 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3049 ScopedCheck sc(flags, function_name);
3050 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3051 if (sc.Check(soa, true, "Esp", args)) {
3052 JniValueType result;
3053 if (utf) {
3054 CHECK(!critical);
3055 result.u = baseEnv(env)->GetStringUTFChars(env, string, is_copy);
3056 } else {
3057 if (critical) {
3058 result.p = baseEnv(env)->GetStringCritical(env, string, is_copy);
3059 } else {
3060 result.p = baseEnv(env)->GetStringChars(env, string, is_copy);
3061 }
3062 }
3063 // TODO: could we be smarter about not copying when local_is_copy?
3064 if (result.p != nullptr && soa.ForceCopy()) {
3065 if (utf) {
3066 size_t length_in_bytes = strlen(result.u) + 1;
3067 result.u =
3068 reinterpret_cast<const char*>(GuardedCopy::Create(result.u, length_in_bytes, false));
3069 } else {
3070 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3071 result.p =
3072 reinterpret_cast<const jchar*>(GuardedCopy::Create(result.p, length_in_bytes, false));
3073 }
3074 if (is_copy != nullptr) {
3075 *is_copy = JNI_TRUE;
3076 }
3077 }
3078 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3079 return utf ? result.u : result.p;
3080 }
3081 }
3082 return nullptr;
3083 }
3084
3085 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3086 const void* chars, bool utf, bool critical) {
3087 ScopedObjectAccess soa(env);
3088 int flags = kFlag_ExcepOkay | kFlag_Release;
3089 if (critical) {
3090 flags |= kFlag_CritRelease;
3091 }
3092 ScopedCheck sc(flags, function_name);
3093 sc.CheckNonNull(chars);
3094 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3095 if (force_copy_ok && soa.ForceCopy()) {
3096 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3097 }
3098 if (force_copy_ok) {
3099 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3100 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3101 if (utf) {
3102 CHECK(!critical);
3103 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3104 } else {
3105 if (critical) {
3106 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3107 } else {
3108 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3109 }
3110 }
3111 JniValueType result;
3112 sc.Check(soa, false, "V", &result);
3113 }
3114 }
3115 }
3116
3117 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3118 Primitive::Type type) {
3119 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003120 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003121 JniValueType args[2] = {{.E = env}, {.z = length}};
3122 if (sc.Check(soa, true, "Ez", args)) {
3123 JniValueType result;
3124 switch (type) {
3125 case Primitive::kPrimBoolean:
3126 result.a = baseEnv(env)->NewBooleanArray(env, length);
3127 break;
3128 case Primitive::kPrimByte:
3129 result.a = baseEnv(env)->NewByteArray(env, length);
3130 break;
3131 case Primitive::kPrimChar:
3132 result.a = baseEnv(env)->NewCharArray(env, length);
3133 break;
3134 case Primitive::kPrimShort:
3135 result.a = baseEnv(env)->NewShortArray(env, length);
3136 break;
3137 case Primitive::kPrimInt:
3138 result.a = baseEnv(env)->NewIntArray(env, length);
3139 break;
3140 case Primitive::kPrimLong:
3141 result.a = baseEnv(env)->NewLongArray(env, length);
3142 break;
3143 case Primitive::kPrimFloat:
3144 result.a = baseEnv(env)->NewFloatArray(env, length);
3145 break;
3146 case Primitive::kPrimDouble:
3147 result.a = baseEnv(env)->NewDoubleArray(env, length);
3148 break;
3149 default:
3150 LOG(FATAL) << "Unexpected primitive type: " << type;
3151 }
3152 if (sc.Check(soa, false, "a", &result)) {
3153 return result.a;
3154 }
3155 }
3156 return nullptr;
3157 }
3158
3159 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3160 JNIEnv* env, jarray array, jboolean* is_copy) {
3161 ScopedObjectAccess soa(env);
3162 ScopedCheck sc(kFlag_Default, function_name);
3163 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3164 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3165 JniValueType result;
3166 switch (type) {
3167 case Primitive::kPrimBoolean:
3168 result.p = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3169 is_copy);
3170 break;
3171 case Primitive::kPrimByte:
3172 result.p = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array),
3173 is_copy);
3174 break;
3175 case Primitive::kPrimChar:
3176 result.p = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array),
3177 is_copy);
3178 break;
3179 case Primitive::kPrimShort:
3180 result.p = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array),
3181 is_copy);
3182 break;
3183 case Primitive::kPrimInt:
3184 result.p = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
3185 break;
3186 case Primitive::kPrimLong:
3187 result.p = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array),
3188 is_copy);
3189 break;
3190 case Primitive::kPrimFloat:
3191 result.p = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array),
3192 is_copy);
3193 break;
3194 case Primitive::kPrimDouble:
3195 result.p = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3196 is_copy);
3197 break;
3198 default:
3199 LOG(FATAL) << "Unexpected primitive type: " << type;
3200 }
3201 if (result.p != nullptr && soa.ForceCopy()) {
3202 result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
3203 if (is_copy != nullptr) {
3204 *is_copy = JNI_TRUE;
3205 }
3206 }
3207 if (sc.Check(soa, false, "p", &result)) {
3208 return const_cast<void*>(result.p);
3209 }
3210 }
3211 return nullptr;
3212 }
3213
3214 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3215 JNIEnv* env, jarray array, void* elems, jint mode) {
3216 ScopedObjectAccess soa(env);
3217 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3218 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3219 if (soa.ForceCopy()) {
3220 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3221 }
3222 if (!soa.ForceCopy() || elems != nullptr) {
3223 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3224 if (sc.Check(soa, true, "Eapr", args)) {
3225 switch (type) {
3226 case Primitive::kPrimBoolean:
3227 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3228 reinterpret_cast<jboolean*>(elems), mode);
3229 break;
3230 case Primitive::kPrimByte:
3231 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3232 reinterpret_cast<jbyte*>(elems), mode);
3233 break;
3234 case Primitive::kPrimChar:
3235 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3236 reinterpret_cast<jchar*>(elems), mode);
3237 break;
3238 case Primitive::kPrimShort:
3239 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3240 reinterpret_cast<jshort*>(elems), mode);
3241 break;
3242 case Primitive::kPrimInt:
3243 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3244 reinterpret_cast<jint*>(elems), mode);
3245 break;
3246 case Primitive::kPrimLong:
3247 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3248 reinterpret_cast<jlong*>(elems), mode);
3249 break;
3250 case Primitive::kPrimFloat:
3251 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3252 reinterpret_cast<jfloat*>(elems), mode);
3253 break;
3254 case Primitive::kPrimDouble:
3255 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3256 reinterpret_cast<jdouble*>(elems), mode);
3257 break;
3258 default:
3259 LOG(FATAL) << "Unexpected primitive type: " << type;
3260 }
3261 JniValueType result;
3262 result.V = nullptr;
3263 sc.Check(soa, false, "V", &result);
3264 }
3265 }
3266 }
3267 }
3268
3269 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3270 jarray array, jsize start, jsize len, void* buf) {
3271 ScopedObjectAccess soa(env);
3272 ScopedCheck sc(kFlag_Default, function_name);
3273 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3274 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3275 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3276 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3277 switch (type) {
3278 case Primitive::kPrimBoolean:
3279 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3280 reinterpret_cast<jboolean*>(buf));
3281 break;
3282 case Primitive::kPrimByte:
3283 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3284 reinterpret_cast<jbyte*>(buf));
3285 break;
3286 case Primitive::kPrimChar:
3287 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3288 reinterpret_cast<jchar*>(buf));
3289 break;
3290 case Primitive::kPrimShort:
3291 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3292 reinterpret_cast<jshort*>(buf));
3293 break;
3294 case Primitive::kPrimInt:
3295 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3296 reinterpret_cast<jint*>(buf));
3297 break;
3298 case Primitive::kPrimLong:
3299 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3300 reinterpret_cast<jlong*>(buf));
3301 break;
3302 case Primitive::kPrimFloat:
3303 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3304 reinterpret_cast<jfloat*>(buf));
3305 break;
3306 case Primitive::kPrimDouble:
3307 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3308 reinterpret_cast<jdouble*>(buf));
3309 break;
3310 default:
3311 LOG(FATAL) << "Unexpected primitive type: " << type;
3312 }
3313 JniValueType result;
3314 result.V = nullptr;
3315 sc.Check(soa, false, "V", &result);
3316 }
3317 }
3318
3319 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3320 jarray array, jsize start, jsize len, const void* buf) {
3321 ScopedObjectAccess soa(env);
3322 ScopedCheck sc(kFlag_Default, function_name);
3323 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3324 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3325 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3326 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3327 switch (type) {
3328 case Primitive::kPrimBoolean:
3329 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3330 reinterpret_cast<const jboolean*>(buf));
3331 break;
3332 case Primitive::kPrimByte:
3333 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3334 reinterpret_cast<const jbyte*>(buf));
3335 break;
3336 case Primitive::kPrimChar:
3337 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3338 reinterpret_cast<const jchar*>(buf));
3339 break;
3340 case Primitive::kPrimShort:
3341 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3342 reinterpret_cast<const jshort*>(buf));
3343 break;
3344 case Primitive::kPrimInt:
3345 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3346 reinterpret_cast<const jint*>(buf));
3347 break;
3348 case Primitive::kPrimLong:
3349 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3350 reinterpret_cast<const jlong*>(buf));
3351 break;
3352 case Primitive::kPrimFloat:
3353 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3354 reinterpret_cast<const jfloat*>(buf));
3355 break;
3356 case Primitive::kPrimDouble:
3357 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3358 reinterpret_cast<const jdouble*>(buf));
3359 break;
3360 default:
3361 LOG(FATAL) << "Unexpected primitive type: " << type;
3362 }
3363 JniValueType result;
3364 result.V = nullptr;
3365 sc.Check(soa, false, "V", &result);
3366 }
3367 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003368};
3369
3370const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003371 nullptr, // reserved0.
3372 nullptr, // reserved1.
3373 nullptr, // reserved2.
3374 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003375 CheckJNI::GetVersion,
3376 CheckJNI::DefineClass,
3377 CheckJNI::FindClass,
3378 CheckJNI::FromReflectedMethod,
3379 CheckJNI::FromReflectedField,
3380 CheckJNI::ToReflectedMethod,
3381 CheckJNI::GetSuperclass,
3382 CheckJNI::IsAssignableFrom,
3383 CheckJNI::ToReflectedField,
3384 CheckJNI::Throw,
3385 CheckJNI::ThrowNew,
3386 CheckJNI::ExceptionOccurred,
3387 CheckJNI::ExceptionDescribe,
3388 CheckJNI::ExceptionClear,
3389 CheckJNI::FatalError,
3390 CheckJNI::PushLocalFrame,
3391 CheckJNI::PopLocalFrame,
3392 CheckJNI::NewGlobalRef,
3393 CheckJNI::DeleteGlobalRef,
3394 CheckJNI::DeleteLocalRef,
3395 CheckJNI::IsSameObject,
3396 CheckJNI::NewLocalRef,
3397 CheckJNI::EnsureLocalCapacity,
3398 CheckJNI::AllocObject,
3399 CheckJNI::NewObject,
3400 CheckJNI::NewObjectV,
3401 CheckJNI::NewObjectA,
3402 CheckJNI::GetObjectClass,
3403 CheckJNI::IsInstanceOf,
3404 CheckJNI::GetMethodID,
3405 CheckJNI::CallObjectMethod,
3406 CheckJNI::CallObjectMethodV,
3407 CheckJNI::CallObjectMethodA,
3408 CheckJNI::CallBooleanMethod,
3409 CheckJNI::CallBooleanMethodV,
3410 CheckJNI::CallBooleanMethodA,
3411 CheckJNI::CallByteMethod,
3412 CheckJNI::CallByteMethodV,
3413 CheckJNI::CallByteMethodA,
3414 CheckJNI::CallCharMethod,
3415 CheckJNI::CallCharMethodV,
3416 CheckJNI::CallCharMethodA,
3417 CheckJNI::CallShortMethod,
3418 CheckJNI::CallShortMethodV,
3419 CheckJNI::CallShortMethodA,
3420 CheckJNI::CallIntMethod,
3421 CheckJNI::CallIntMethodV,
3422 CheckJNI::CallIntMethodA,
3423 CheckJNI::CallLongMethod,
3424 CheckJNI::CallLongMethodV,
3425 CheckJNI::CallLongMethodA,
3426 CheckJNI::CallFloatMethod,
3427 CheckJNI::CallFloatMethodV,
3428 CheckJNI::CallFloatMethodA,
3429 CheckJNI::CallDoubleMethod,
3430 CheckJNI::CallDoubleMethodV,
3431 CheckJNI::CallDoubleMethodA,
3432 CheckJNI::CallVoidMethod,
3433 CheckJNI::CallVoidMethodV,
3434 CheckJNI::CallVoidMethodA,
3435 CheckJNI::CallNonvirtualObjectMethod,
3436 CheckJNI::CallNonvirtualObjectMethodV,
3437 CheckJNI::CallNonvirtualObjectMethodA,
3438 CheckJNI::CallNonvirtualBooleanMethod,
3439 CheckJNI::CallNonvirtualBooleanMethodV,
3440 CheckJNI::CallNonvirtualBooleanMethodA,
3441 CheckJNI::CallNonvirtualByteMethod,
3442 CheckJNI::CallNonvirtualByteMethodV,
3443 CheckJNI::CallNonvirtualByteMethodA,
3444 CheckJNI::CallNonvirtualCharMethod,
3445 CheckJNI::CallNonvirtualCharMethodV,
3446 CheckJNI::CallNonvirtualCharMethodA,
3447 CheckJNI::CallNonvirtualShortMethod,
3448 CheckJNI::CallNonvirtualShortMethodV,
3449 CheckJNI::CallNonvirtualShortMethodA,
3450 CheckJNI::CallNonvirtualIntMethod,
3451 CheckJNI::CallNonvirtualIntMethodV,
3452 CheckJNI::CallNonvirtualIntMethodA,
3453 CheckJNI::CallNonvirtualLongMethod,
3454 CheckJNI::CallNonvirtualLongMethodV,
3455 CheckJNI::CallNonvirtualLongMethodA,
3456 CheckJNI::CallNonvirtualFloatMethod,
3457 CheckJNI::CallNonvirtualFloatMethodV,
3458 CheckJNI::CallNonvirtualFloatMethodA,
3459 CheckJNI::CallNonvirtualDoubleMethod,
3460 CheckJNI::CallNonvirtualDoubleMethodV,
3461 CheckJNI::CallNonvirtualDoubleMethodA,
3462 CheckJNI::CallNonvirtualVoidMethod,
3463 CheckJNI::CallNonvirtualVoidMethodV,
3464 CheckJNI::CallNonvirtualVoidMethodA,
3465 CheckJNI::GetFieldID,
3466 CheckJNI::GetObjectField,
3467 CheckJNI::GetBooleanField,
3468 CheckJNI::GetByteField,
3469 CheckJNI::GetCharField,
3470 CheckJNI::GetShortField,
3471 CheckJNI::GetIntField,
3472 CheckJNI::GetLongField,
3473 CheckJNI::GetFloatField,
3474 CheckJNI::GetDoubleField,
3475 CheckJNI::SetObjectField,
3476 CheckJNI::SetBooleanField,
3477 CheckJNI::SetByteField,
3478 CheckJNI::SetCharField,
3479 CheckJNI::SetShortField,
3480 CheckJNI::SetIntField,
3481 CheckJNI::SetLongField,
3482 CheckJNI::SetFloatField,
3483 CheckJNI::SetDoubleField,
3484 CheckJNI::GetStaticMethodID,
3485 CheckJNI::CallStaticObjectMethod,
3486 CheckJNI::CallStaticObjectMethodV,
3487 CheckJNI::CallStaticObjectMethodA,
3488 CheckJNI::CallStaticBooleanMethod,
3489 CheckJNI::CallStaticBooleanMethodV,
3490 CheckJNI::CallStaticBooleanMethodA,
3491 CheckJNI::CallStaticByteMethod,
3492 CheckJNI::CallStaticByteMethodV,
3493 CheckJNI::CallStaticByteMethodA,
3494 CheckJNI::CallStaticCharMethod,
3495 CheckJNI::CallStaticCharMethodV,
3496 CheckJNI::CallStaticCharMethodA,
3497 CheckJNI::CallStaticShortMethod,
3498 CheckJNI::CallStaticShortMethodV,
3499 CheckJNI::CallStaticShortMethodA,
3500 CheckJNI::CallStaticIntMethod,
3501 CheckJNI::CallStaticIntMethodV,
3502 CheckJNI::CallStaticIntMethodA,
3503 CheckJNI::CallStaticLongMethod,
3504 CheckJNI::CallStaticLongMethodV,
3505 CheckJNI::CallStaticLongMethodA,
3506 CheckJNI::CallStaticFloatMethod,
3507 CheckJNI::CallStaticFloatMethodV,
3508 CheckJNI::CallStaticFloatMethodA,
3509 CheckJNI::CallStaticDoubleMethod,
3510 CheckJNI::CallStaticDoubleMethodV,
3511 CheckJNI::CallStaticDoubleMethodA,
3512 CheckJNI::CallStaticVoidMethod,
3513 CheckJNI::CallStaticVoidMethodV,
3514 CheckJNI::CallStaticVoidMethodA,
3515 CheckJNI::GetStaticFieldID,
3516 CheckJNI::GetStaticObjectField,
3517 CheckJNI::GetStaticBooleanField,
3518 CheckJNI::GetStaticByteField,
3519 CheckJNI::GetStaticCharField,
3520 CheckJNI::GetStaticShortField,
3521 CheckJNI::GetStaticIntField,
3522 CheckJNI::GetStaticLongField,
3523 CheckJNI::GetStaticFloatField,
3524 CheckJNI::GetStaticDoubleField,
3525 CheckJNI::SetStaticObjectField,
3526 CheckJNI::SetStaticBooleanField,
3527 CheckJNI::SetStaticByteField,
3528 CheckJNI::SetStaticCharField,
3529 CheckJNI::SetStaticShortField,
3530 CheckJNI::SetStaticIntField,
3531 CheckJNI::SetStaticLongField,
3532 CheckJNI::SetStaticFloatField,
3533 CheckJNI::SetStaticDoubleField,
3534 CheckJNI::NewString,
3535 CheckJNI::GetStringLength,
3536 CheckJNI::GetStringChars,
3537 CheckJNI::ReleaseStringChars,
3538 CheckJNI::NewStringUTF,
3539 CheckJNI::GetStringUTFLength,
3540 CheckJNI::GetStringUTFChars,
3541 CheckJNI::ReleaseStringUTFChars,
3542 CheckJNI::GetArrayLength,
3543 CheckJNI::NewObjectArray,
3544 CheckJNI::GetObjectArrayElement,
3545 CheckJNI::SetObjectArrayElement,
3546 CheckJNI::NewBooleanArray,
3547 CheckJNI::NewByteArray,
3548 CheckJNI::NewCharArray,
3549 CheckJNI::NewShortArray,
3550 CheckJNI::NewIntArray,
3551 CheckJNI::NewLongArray,
3552 CheckJNI::NewFloatArray,
3553 CheckJNI::NewDoubleArray,
3554 CheckJNI::GetBooleanArrayElements,
3555 CheckJNI::GetByteArrayElements,
3556 CheckJNI::GetCharArrayElements,
3557 CheckJNI::GetShortArrayElements,
3558 CheckJNI::GetIntArrayElements,
3559 CheckJNI::GetLongArrayElements,
3560 CheckJNI::GetFloatArrayElements,
3561 CheckJNI::GetDoubleArrayElements,
3562 CheckJNI::ReleaseBooleanArrayElements,
3563 CheckJNI::ReleaseByteArrayElements,
3564 CheckJNI::ReleaseCharArrayElements,
3565 CheckJNI::ReleaseShortArrayElements,
3566 CheckJNI::ReleaseIntArrayElements,
3567 CheckJNI::ReleaseLongArrayElements,
3568 CheckJNI::ReleaseFloatArrayElements,
3569 CheckJNI::ReleaseDoubleArrayElements,
3570 CheckJNI::GetBooleanArrayRegion,
3571 CheckJNI::GetByteArrayRegion,
3572 CheckJNI::GetCharArrayRegion,
3573 CheckJNI::GetShortArrayRegion,
3574 CheckJNI::GetIntArrayRegion,
3575 CheckJNI::GetLongArrayRegion,
3576 CheckJNI::GetFloatArrayRegion,
3577 CheckJNI::GetDoubleArrayRegion,
3578 CheckJNI::SetBooleanArrayRegion,
3579 CheckJNI::SetByteArrayRegion,
3580 CheckJNI::SetCharArrayRegion,
3581 CheckJNI::SetShortArrayRegion,
3582 CheckJNI::SetIntArrayRegion,
3583 CheckJNI::SetLongArrayRegion,
3584 CheckJNI::SetFloatArrayRegion,
3585 CheckJNI::SetDoubleArrayRegion,
3586 CheckJNI::RegisterNatives,
3587 CheckJNI::UnregisterNatives,
3588 CheckJNI::MonitorEnter,
3589 CheckJNI::MonitorExit,
3590 CheckJNI::GetJavaVM,
3591 CheckJNI::GetStringRegion,
3592 CheckJNI::GetStringUTFRegion,
3593 CheckJNI::GetPrimitiveArrayCritical,
3594 CheckJNI::ReleasePrimitiveArrayCritical,
3595 CheckJNI::GetStringCritical,
3596 CheckJNI::ReleaseStringCritical,
3597 CheckJNI::NewWeakGlobalRef,
3598 CheckJNI::DeleteWeakGlobalRef,
3599 CheckJNI::ExceptionCheck,
3600 CheckJNI::NewDirectByteBuffer,
3601 CheckJNI::GetDirectBufferAddress,
3602 CheckJNI::GetDirectBufferCapacity,
3603 CheckJNI::GetObjectRefType,
3604};
3605
3606const JNINativeInterface* GetCheckJniNativeInterface() {
3607 return &gCheckNativeInterface;
3608}
3609
3610class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003611 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003612 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003613 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3614 JniValueType args[1] = {{.v = vm}};
3615 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3616 JniValueType result;
3617 result.i = BaseVm(vm)->DestroyJavaVM(vm);
3618 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3619 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003620 }
3621
3622 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003623 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3624 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3625 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3626 JniValueType result;
3627 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3628 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3629 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003630 }
3631
3632 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003633 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3634 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3635 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3636 JniValueType result;
3637 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3638 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3639 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003640 }
3641
3642 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003643 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3644 JniValueType args[1] = {{.v = vm}};
3645 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3646 JniValueType result;
3647 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3648 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3649 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003650 }
3651
Ian Rogers68d8b422014-07-17 11:09:10 -07003652 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3653 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3654 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3655 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3656 JniValueType result;
3657 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3658 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3659 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003660 }
3661
3662 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003663 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3664 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003665 }
3666};
3667
3668const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003669 nullptr, // reserved0
3670 nullptr, // reserved1
3671 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003672 CheckJII::DestroyJavaVM,
3673 CheckJII::AttachCurrentThread,
3674 CheckJII::DetachCurrentThread,
3675 CheckJII::GetEnv,
3676 CheckJII::AttachCurrentThreadAsDaemon
3677};
3678
3679const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3680 return &gCheckInvokeInterface;
3681}
3682
3683} // namespace art