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