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