blob: b0f8e22ab2e861b26eab4e3719463fc95695c74f [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);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700653 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700654 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700655 AbortF("%s is an invalid %s: %p (%p)",
656 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
657 java_object, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800658 return false;
659 }
660
661 bool okay = true;
662 switch (kind) {
663 case kClass:
664 okay = obj->IsClass();
665 break;
666 case kDirectByteBuffer:
667 UNIMPLEMENTED(FATAL);
668 break;
669 case kString:
670 okay = obj->GetClass()->IsStringClass();
671 break;
672 case kThrowable:
673 okay = obj->GetClass()->IsThrowableClass();
674 break;
675 case kObject:
676 break;
677 }
678 if (!okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700679 AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800680 return false;
681 }
682
683 return true;
684 }
685
Ian Rogers68d8b422014-07-17 11:09:10 -0700686 /*
687 * Verify that the "mode" argument passed to a primitive array Release
688 * function is one of the valid values.
689 */
690 bool CheckReleaseMode(jint mode) {
691 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
692 AbortF("unknown value for release mode: %d", mode);
693 return false;
694 }
695 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700696 }
697
Ian Rogers68d8b422014-07-17 11:09:10 -0700698 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
699 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
700 switch (fmt) {
701 case 'a': // jarray
702 return CheckArray(soa, arg.a);
703 case 'c': // jclass
704 return CheckInstance(soa, kClass, arg.c, false);
705 case 'f': // jfieldID
706 return CheckFieldID(soa, arg.f) != nullptr;
707 case 'm': // jmethodID
708 return CheckMethodID(soa, arg.m) != nullptr;
709 case 'r': // release int
710 return CheckReleaseMode(arg.r);
711 case 's': // jstring
712 return CheckInstance(soa, kString, arg.s, false);
713 case 't': // jthrowable
714 return CheckInstance(soa, kThrowable, arg.t, false);
715 case 'E': // JNIEnv*
716 return CheckThread(arg.E);
717 case 'L': // jobject
718 return CheckInstance(soa, kObject, arg.L, true);
719 default:
720 return CheckNonHeapValue(fmt, arg);
721 }
722 }
723
724 bool CheckNonHeapValue(char fmt, JniValueType arg) {
725 switch (fmt) {
726 case '.': // ...
727 case 'p': // TODO: pointer - null or readable?
728 case 'v': // JavaVM*
729 case 'B': // jbyte
730 case 'C': // jchar
731 case 'D': // jdouble
732 case 'F': // jfloat
733 case 'I': // jint
734 case 'J': // jlong
735 case 'S': // jshort
736 break; // Ignored.
737 case 'b': // jboolean, why two? Fall-through.
738 case 'Z':
739 return CheckBoolean(arg.Z);
740 case 'u': // utf8
741 if ((flags_ & kFlag_Release) != 0) {
742 return CheckNonNull(arg.u);
743 } else {
744 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
745 return CheckUtfString(arg.u, nullable);
746 }
747 case 'w': // jobjectRefType
748 switch (arg.w) {
749 case JNIInvalidRefType:
750 case JNILocalRefType:
751 case JNIGlobalRefType:
752 case JNIWeakGlobalRefType:
753 break;
754 default:
755 AbortF("Unknown reference type");
756 return false;
757 }
758 break;
759 case 'z': // jsize
760 return CheckLengthPositive(arg.z);
761 default:
762 AbortF("unknown format specifier: '%c'", fmt);
763 return false;
764 }
765 return true;
766 }
767
768 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
769 std::string* msg)
770 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
771 switch (fmt) {
772 case 'L': // jobject fall-through.
773 case 'a': // jarray fall-through.
774 case 's': // jstring fall-through.
775 case 't': // jthrowable fall-through.
776 if (arg.L == nullptr) {
777 *msg += "NULL";
778 } else {
779 StringAppendF(msg, "%p", arg.L);
780 }
781 break;
782 case 'c': { // jclass
783 jclass jc = arg.c;
784 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
785 if (c == nullptr) {
786 *msg += "NULL";
787 } else if (c == kInvalidIndirectRefObject ||
788 !Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
789 StringAppendF(msg, "INVALID POINTER:%p", jc);
790 } else if (!c->IsClass()) {
791 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
792 } else {
793 *msg += PrettyClass(c);
794 if (!entry) {
795 StringAppendF(msg, " (%p)", jc);
796 }
797 }
798 break;
799 }
800 case 'f': { // jfieldID
801 jfieldID fid = arg.f;
802 mirror::ArtField* f = soa.DecodeField(fid);
803 *msg += PrettyField(f);
804 if (!entry) {
805 StringAppendF(msg, " (%p)", fid);
806 }
807 break;
808 }
809 case 'm': { // jmethodID
810 jmethodID mid = arg.m;
811 mirror::ArtMethod* m = soa.DecodeMethod(mid);
812 *msg += PrettyMethod(m);
813 if (!entry) {
814 StringAppendF(msg, " (%p)", mid);
815 }
816 break;
817 }
818 default:
819 TraceNonHeapValue(fmt, arg, msg);
820 break;
821 }
822 }
823
824 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
825 switch (fmt) {
826 case 'B': // jbyte
827 if (arg.B >= 0 && arg.B < 10) {
828 StringAppendF(msg, "%d", arg.B);
829 } else {
830 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
831 }
832 break;
833 case 'C': // jchar
834 if (arg.C < 0x7f && arg.C >= ' ') {
835 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
836 } else {
837 StringAppendF(msg, "U+%x", arg.C);
838 }
839 break;
840 case 'F': // jfloat
841 StringAppendF(msg, "%g", arg.F);
842 break;
843 case 'D': // jdouble
844 StringAppendF(msg, "%g", arg.D);
845 break;
846 case 'S': // jshort
847 StringAppendF(msg, "%d", arg.S);
848 break;
849 case 'i': // jint - fall-through.
850 case 'I': // jint
851 StringAppendF(msg, "%d", arg.I);
852 break;
853 case 'J': // jlong
854 StringAppendF(msg, "%" PRId64, arg.J);
855 break;
856 case 'Z': // jboolean
857 case 'b': // jboolean (JNI-style)
858 *msg += arg.b == JNI_TRUE ? "true" : "false";
859 break;
860 case 'V': // void
861 DCHECK(arg.V == nullptr);
862 *msg += "void";
863 break;
864 case 'v': // JavaVM*
865 StringAppendF(msg, "(JavaVM*)%p", arg.v);
866 break;
867 case 'E':
868 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
869 break;
870 case 'z': // non-negative jsize
871 // You might expect jsize to be size_t, but it's not; it's the same as jint.
872 // We only treat this specially so we can do the non-negative check.
873 // TODO: maybe this wasn't worth it?
874 StringAppendF(msg, "%d", arg.z);
875 break;
876 case 'p': // void* ("pointer")
877 if (arg.p == nullptr) {
878 *msg += "NULL";
879 } else {
880 StringAppendF(msg, "(void*) %p", arg.p);
881 }
882 break;
883 case 'r': { // jint (release mode)
884 jint releaseMode = arg.r;
885 if (releaseMode == 0) {
886 *msg += "0";
887 } else if (releaseMode == JNI_ABORT) {
888 *msg += "JNI_ABORT";
889 } else if (releaseMode == JNI_COMMIT) {
890 *msg += "JNI_COMMIT";
891 } else {
892 StringAppendF(msg, "invalid release mode %d", releaseMode);
893 }
894 break;
895 }
896 case 'u': // const char* (Modified UTF-8)
897 if (arg.u == nullptr) {
898 *msg += "NULL";
899 } else {
900 StringAppendF(msg, "\"%s\"", arg.u);
901 }
902 break;
903 case 'w': // jobjectRefType
904 switch (arg.w) {
905 case JNIInvalidRefType:
906 *msg += "invalid reference type";
907 break;
908 case JNILocalRefType:
909 *msg += "local ref type";
910 break;
911 case JNIGlobalRefType:
912 *msg += "global ref type";
913 break;
914 case JNIWeakGlobalRefType:
915 *msg += "weak global ref type";
916 break;
917 default:
918 *msg += "unknown ref type";
919 break;
920 }
921 break;
922 case '.':
923 *msg += "...";
924 break;
925 default:
926 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
927 }
928 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700929 /*
930 * Verify that "array" is non-NULL and points to an Array object.
931 *
932 * Since we're dealing with objects, switch to "running" mode.
933 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700934 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
935 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
936 if (UNLIKELY(java_array == nullptr)) {
937 AbortF("jarray was NULL");
938 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700939 }
940
Ian Rogers68d8b422014-07-17 11:09:10 -0700941 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
942 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700943 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700944 AbortF("jarray is an invalid %s: %p (%p)",
945 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
946 java_array, a);
947 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700948 } else if (!a->IsArrayInstance()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700949 AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
950 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700951 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700952 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700953 }
954
Ian Rogers68d8b422014-07-17 11:09:10 -0700955 bool CheckBoolean(jboolean z) {
956 if (z != JNI_TRUE && z != JNI_FALSE) {
957 AbortF("unexpected jboolean value: %d", z);
958 return false;
959 }
960 return true;
961 }
962
963 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700964 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700965 AbortF("negative jsize: %d", length);
966 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700967 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700968 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700969 }
970
Ian Rogers68d8b422014-07-17 11:09:10 -0700971 mirror::ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
972 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800973 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700974 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -0800975 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700976 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700977 mirror::ArtField* f = soa.DecodeField(fid);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700978 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700979 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700980 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800981 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700982 }
983 return f;
984 }
985
Ian Rogers68d8b422014-07-17 11:09:10 -0700986 mirror::ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
987 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800988 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700989 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -0800990 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700991 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700992 mirror::ArtMethod* m = soa.DecodeMethod(mid);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700993 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700994 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700995 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800996 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700997 }
998 return m;
999 }
1000
Ian Rogers68d8b422014-07-17 11:09:10 -07001001 bool CheckThread(JNIEnv* env) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001002 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001003 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001004 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1005 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001006 }
1007
1008 // Get the *correct* JNIEnv by going through our TLS pointer.
1009 JNIEnvExt* threadEnv = self->GetJniEnv();
1010
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001011 // Verify that the current thread is (a) attached and (b) associated with
1012 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001013 if (env != threadEnv) {
1014 AbortF("thread %s using JNIEnv* from thread %s",
1015 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
1016 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001017 }
1018
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001019 // Verify that, if this thread previously made a critical "get" call, we
1020 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001021 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001022 case kFlag_CritOkay: // okay to call this method
1023 break;
1024 case kFlag_CritBad: // not okay to call
1025 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001026 AbortF("thread %s using JNI after critical get",
1027 ToStr<Thread>(*self).c_str());
1028 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001029 }
1030 break;
1031 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001032 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001033 threadEnv->critical++;
1034 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001035 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001036 threadEnv->critical--;
1037 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001038 AbortF("thread %s called too many critical releases",
1039 ToStr<Thread>(*self).c_str());
1040 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001041 }
1042 break;
1043 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001044 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001045 }
1046
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001047 // Verify that, if an exception has been raised, the native code doesn't
1048 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001049 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001050 ThrowLocation throw_location;
1051 mirror::Throwable* exception = self->GetException(&throw_location);
1052 std::string type(PrettyTypeOf(exception));
Ian Rogers68d8b422014-07-17 11:09:10 -07001053 AbortF("JNI %s called with pending exception '%s' thrown in %s",
1054 function_name_, type.c_str(), throw_location.Dump().c_str());
1055 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001056 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001057 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001058 }
1059
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001060 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001061 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001062 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001063 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001064 AbortF("non-nullable const char* was NULL");
1065 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001066 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001067 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001068 }
1069
Ian Rogersef7d42f2014-01-06 12:55:46 -08001070 const char* errorKind = nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001071 uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001072 if (errorKind != nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001073 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1074 " string: '%s'", errorKind, utf8, bytes);
1075 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001076 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001077 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001078 }
1079
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001080 static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001081 while (*bytes != '\0') {
1082 uint8_t utf8 = *(bytes++);
1083 // Switch on the high four bits.
1084 switch (utf8 >> 4) {
1085 case 0x00:
1086 case 0x01:
1087 case 0x02:
1088 case 0x03:
1089 case 0x04:
1090 case 0x05:
1091 case 0x06:
1092 case 0x07:
1093 // Bit pattern 0xxx. No need for any extra bytes.
1094 break;
1095 case 0x08:
1096 case 0x09:
1097 case 0x0a:
1098 case 0x0b:
1099 case 0x0f:
1100 /*
1101 * Bit pattern 10xx or 1111, which are illegal start bytes.
1102 * Note: 1111 is valid for normal UTF-8, but not the
Elliott Hughes78090d12011-10-07 14:31:47 -07001103 * Modified UTF-8 used here.
Elliott Hughesa2501992011-08-26 19:39:54 -07001104 */
1105 *errorKind = "start";
1106 return utf8;
1107 case 0x0e:
1108 // Bit pattern 1110, so there are two additional bytes.
1109 utf8 = *(bytes++);
1110 if ((utf8 & 0xc0) != 0x80) {
1111 *errorKind = "continuation";
1112 return utf8;
1113 }
1114 // Fall through to take care of the final byte.
1115 case 0x0c:
1116 case 0x0d:
1117 // Bit pattern 110x, so there is one additional byte.
1118 utf8 = *(bytes++);
1119 if ((utf8 & 0xc0) != 0x80) {
1120 *errorKind = "continuation";
1121 return utf8;
1122 }
1123 break;
1124 }
1125 }
1126 return 0;
1127 }
1128
Ian Rogers68d8b422014-07-17 11:09:10 -07001129 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1130 va_list args;
1131 va_start(args, fmt);
1132 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1133 va_end(args);
1134 }
1135
1136 // The name of the JNI function being checked.
1137 const char* const function_name_;
1138
1139 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001140 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001141
Ian Rogers68d8b422014-07-17 11:09:10 -07001142 const bool has_method_;
1143
Elliott Hughesa2501992011-08-26 19:39:54 -07001144 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1145};
1146
Elliott Hughesa2501992011-08-26 19:39:54 -07001147/*
1148 * ===========================================================================
1149 * Guarded arrays
1150 * ===========================================================================
1151 */
1152
Elliott Hughesa2501992011-08-26 19:39:54 -07001153/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001154class GuardedCopy {
1155 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001156 /*
1157 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1158 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001159 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001160 static void* Create(const void* original_buf, size_t len, bool mod_okay) {
1161 const size_t new_len = LengthIncludingRedZones(len);
1162 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001163
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001164 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001165 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001166 if (!mod_okay) {
1167 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001168 }
1169
Ian Rogers68d8b422014-07-17 11:09:10 -07001170 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001171
Ian Rogers68d8b422014-07-17 11:09:10 -07001172 // Fill begin region with canary pattern.
1173 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1174 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1175 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1176 if (kCanary[j] == '\0') {
1177 j = 0;
1178 }
1179 }
1180
1181 // Copy the data in; note "len" could be zero.
1182 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1183
1184 // Fill end region with canary pattern.
1185 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1186 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1187 if (kCanary[j] == '\0') {
1188 j = 0;
1189 }
1190 }
1191
1192 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001193 }
1194
1195 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001196 * Create a guarded copy of a primitive array. Modifications to the copied
1197 * data are allowed. Returns a pointer to the copied data.
1198 */
1199 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy) {
1200 ScopedObjectAccess soa(env);
1201
1202 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1203 size_t component_size = a->GetClass()->GetComponentSize();
1204 size_t byte_count = a->GetLength() * component_size;
1205 void* result = Create(a->GetRawData(component_size, 0), byte_count, true);
1206 if (is_copy != nullptr) {
1207 *is_copy = JNI_TRUE;
1208 }
1209 return result;
1210 }
1211
1212 /*
1213 * Perform the array "release" operation, which may or may not copy data
1214 * back into the managed heap, and may or may not release the underlying storage.
1215 */
1216 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, jarray java_array,
1217 void* embedded_buf, int mode) {
1218 ScopedObjectAccess soa(env);
1219 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1220
1221 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1222 return nullptr;
1223 }
1224 if (mode != JNI_ABORT) {
1225 size_t len = FromEmbedded(embedded_buf)->original_length_;
1226 memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), embedded_buf, len);
1227 }
1228 if (mode != JNI_COMMIT) {
1229 return Destroy(embedded_buf);
1230 }
1231 return embedded_buf;
1232 }
1233
1234
1235 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001236 * Free up the guard buffer, scrub it, and return the original pointer.
1237 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001238 static void* Destroy(void* embedded_buf) {
1239 GuardedCopy* copy = FromEmbedded(embedded_buf);
1240 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1241 size_t len = LengthIncludingRedZones(copy->original_length_);
1242 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001243 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001244 }
1245
1246 /*
1247 * Verify the guard area and, if "modOkay" is false, that the data itself
1248 * has not been altered.
1249 *
1250 * The caller has already checked that "dataBuf" is non-NULL.
1251 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001252 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1253 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1254 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001255 }
1256
1257 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07001258 GuardedCopy(const void* original_buf, size_t len, uLong adler) :
1259 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1260 }
1261
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001262 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001263 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001264 if (result == MAP_FAILED) {
1265 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1266 }
1267 return reinterpret_cast<uint8_t*>(result);
1268 }
1269
Ian Rogers68d8b422014-07-17 11:09:10 -07001270 static void DebugFree(void* buf, size_t len) {
1271 if (munmap(buf, len) != 0) {
1272 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001273 }
1274 }
1275
Ian Rogers68d8b422014-07-17 11:09:10 -07001276 static size_t LengthIncludingRedZones(size_t len) {
1277 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001278 }
1279
Ian Rogers68d8b422014-07-17 11:09:10 -07001280 // Get the GuardedCopy from the interior pointer.
1281 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1282 return reinterpret_cast<GuardedCopy*>(
1283 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001284 }
1285
Ian Rogers68d8b422014-07-17 11:09:10 -07001286 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1287 return reinterpret_cast<const GuardedCopy*>(
1288 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001289 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001290
1291 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1292 va_list args;
1293 va_start(args, fmt);
1294 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1295 va_end(args);
1296 }
1297
1298 bool CheckHeader(const char* function_name, bool mod_okay) const {
1299 static const uint32_t kMagicCmp = kGuardMagic;
1300
1301 // Before we do anything with "pExtra", check the magic number. We
1302 // do the check with memcmp rather than "==" in case the pointer is
1303 // unaligned. If it points to completely bogus memory we're going
1304 // to crash, but there's no easy way around that.
1305 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1306 uint8_t buf[4];
1307 memcpy(buf, &magic_, 4);
1308 AbortF(function_name,
1309 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1310 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1311 return false;
1312 }
1313
1314 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1315 // told the client that we made a copy, there's no reason they can't alter the buffer.
1316 if (!mod_okay) {
1317 uLong computed_adler =
1318 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1319 if (computed_adler != adler_) {
1320 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1321 computed_adler, adler_, this);
1322 return false;
1323 }
1324 }
1325 return true;
1326 }
1327
1328 bool CheckRedZones(const char* function_name) const {
1329 // Check the begin red zone.
1330 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1331 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1332 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1333 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1334 return false;
1335 }
1336 if (kCanary[j] == '\0') {
1337 j = 0;
1338 }
1339 }
1340
1341 // Check end region.
1342 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1343 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1344 size_t offset_from_buffer_start =
1345 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1346 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1347 offset_from_buffer_start);
1348 return false;
1349 }
1350 if (kCanary[j] == '\0') {
1351 j = 0;
1352 }
1353 }
1354 return true;
1355 }
1356
1357 // Location that canary value will be written before the guarded region.
1358 const char* StartRedZone() const {
1359 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1360 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1361 }
1362
1363 // Return the interior embedded buffer.
1364 const uint8_t* BufferWithinRedZones() const {
1365 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1366 return embedded_buf;
1367 }
1368
1369 // Location that canary value will be written after the guarded region.
1370 const char* EndRedZone() const {
1371 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1372 size_t buf_len = LengthIncludingRedZones(original_length_);
1373 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1374 }
1375
1376 static constexpr size_t kRedZoneSize = 512;
1377 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1378
1379 // Value written before and after the guarded array.
1380 static const char* const kCanary;
1381
1382 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1383
1384 const uint32_t magic_;
1385 const uLong adler_;
1386 const void* const original_ptr_;
1387 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001388};
Ian Rogers68d8b422014-07-17 11:09:10 -07001389const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001390
1391/*
1392 * ===========================================================================
1393 * JNI functions
1394 * ===========================================================================
1395 */
1396
1397class CheckJNI {
1398 public:
1399 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001400 ScopedObjectAccess soa(env);
1401 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1402 JniValueType args[1] = {{.E = env }};
1403 if (sc.Check(soa, true, "E", args)) {
1404 JniValueType result;
1405 result.I = baseEnv(env)->GetVersion(env);
1406 if (sc.Check(soa, false, "I", &result)) {
1407 return result.I;
1408 }
1409 }
1410 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001411 }
1412
Ian Rogers68d8b422014-07-17 11:09:10 -07001413 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1414 ScopedObjectAccess soa(env);
1415 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1416 JniValueType args[2] = {{.E = env }, {.p = vm}};
1417 if (sc.Check(soa, true, "Ep", args)) {
1418 JniValueType result;
1419 result.i = baseEnv(env)->GetJavaVM(env, vm);
1420 if (sc.Check(soa, false, "i", &result)) {
1421 return result.i;
1422 }
1423 }
1424 return JNI_ERR;
1425 }
1426
1427 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1428 ScopedObjectAccess soa(env);
1429 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1430 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1431 if (sc.Check(soa, true, "EcpI", args)) {
1432 JniValueType result;
1433 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1434 if (sc.Check(soa, false, "i", &result)) {
1435 return result.i;
1436 }
1437 }
1438 return JNI_ERR;
1439 }
1440
1441 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1442 ScopedObjectAccess soa(env);
1443 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1444 JniValueType args[2] = {{.E = env }, {.c = c}};
1445 if (sc.Check(soa, true, "Ec", args)) {
1446 JniValueType result;
1447 result.i = baseEnv(env)->UnregisterNatives(env, c);
1448 if (sc.Check(soa, false, "i", &result)) {
1449 return result.i;
1450 }
1451 }
1452 return JNI_ERR;
1453 }
1454
1455 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1456 // Note: we use "Ep" rather than "EL" because this is the one JNI function that it's okay to
1457 // pass an invalid reference to.
1458 ScopedObjectAccess soa(env);
1459 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1460 JniValueType args[2] = {{.E = env }, {.p = obj}};
1461 if (sc.Check(soa, true, "Ep", args)) {
1462 JniValueType result;
1463 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1464 if (sc.Check(soa, false, "w", &result)) {
1465 return result.w;
1466 }
1467 }
1468 return JNIInvalidRefType;
1469 }
1470
1471 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1472 jsize bufLen) {
1473 ScopedObjectAccess soa(env);
1474 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1475 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1476 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1477 JniValueType result;
1478 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1479 if (sc.Check(soa, false, "c", &result)) {
1480 return result.c;
1481 }
1482 }
1483 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001484 }
1485
1486 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001487 ScopedObjectAccess soa(env);
1488 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1489 JniValueType args[2] = {{.E = env}, {.u = name}};
1490 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1491 JniValueType result;
1492 result.c = baseEnv(env)->FindClass(env, name);
1493 if (sc.Check(soa, false, "c", &result)) {
1494 return result.c;
1495 }
1496 }
1497 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001498 }
1499
Elliott Hughese84278b2012-03-22 10:06:53 -07001500 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001501 ScopedObjectAccess soa(env);
1502 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1503 JniValueType args[2] = {{.E = env}, {.c = c}};
1504 if (sc.Check(soa, true, "Ec", args)) {
1505 JniValueType result;
1506 result.c = baseEnv(env)->GetSuperclass(env, c);
1507 if (sc.Check(soa, false, "c", &result)) {
1508 return result.c;
1509 }
1510 }
1511 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001512 }
1513
Elliott Hughese84278b2012-03-22 10:06:53 -07001514 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001515 ScopedObjectAccess soa(env);
1516 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1517 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1518 if (sc.Check(soa, true, "Ecc", args)) {
1519 JniValueType result;
1520 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1521 if (sc.Check(soa, false, "b", &result)) {
1522 return result.b;
1523 }
1524 }
1525 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001526 }
1527
1528 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001529 ScopedObjectAccess soa(env);
1530 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1531 JniValueType args[2] = {{.E = env}, {.L = method}};
1532 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1533 JniValueType result;
1534 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1535 if (sc.Check(soa, false, "m", &result)) {
1536 return result.m;
1537 }
1538 }
1539 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001540 }
1541
1542 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001543 ScopedObjectAccess soa(env);
1544 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1545 JniValueType args[2] = {{.E = env}, {.L = field}};
1546 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1547 JniValueType result;
1548 result.f = baseEnv(env)->FromReflectedField(env, field);
1549 if (sc.Check(soa, false, "f", &result)) {
1550 return result.f;
1551 }
1552 }
1553 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001554 }
1555
1556 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001557 ScopedObjectAccess soa(env);
1558 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1559 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1560 if (sc.Check(soa, true, "Ecmb", args)) {
1561 JniValueType result;
1562 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1563 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1564 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1565 return result.L;
1566 }
1567 }
1568 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001569 }
1570
1571 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001572 ScopedObjectAccess soa(env);
1573 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1574 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1575 if (sc.Check(soa, true, "Ecfb", args)) {
1576 JniValueType result;
1577 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1578 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1579 DCHECK(sc.CheckReflectedField(soa, result.L));
1580 return result.L;
1581 }
1582 }
1583 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001584 }
1585
1586 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001587 ScopedObjectAccess soa(env);
1588 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1589 JniValueType args[2] = {{.E = env}, {.t = obj}};
1590 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1591 JniValueType result;
1592 result.i = baseEnv(env)->Throw(env, obj);
1593 if (sc.Check(soa, false, "i", &result)) {
1594 return result.i;
1595 }
1596 }
1597 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001598 }
1599
Elliott Hughese84278b2012-03-22 10:06:53 -07001600 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001601 ScopedObjectAccess soa(env);
1602 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
1603 JniValueType args[5] = {{.E = env}, {.c = c}, {.u = message}};
1604 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1605 JniValueType result;
1606 result.i = baseEnv(env)->ThrowNew(env, c, message);
1607 if (sc.Check(soa, false, "i", &result)) {
1608 return result.i;
1609 }
1610 }
1611 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001612 }
1613
1614 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001615 ScopedObjectAccess soa(env);
1616 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1617 JniValueType args[1] = {{.E = env}};
1618 if (sc.Check(soa, true, "E", args)) {
1619 JniValueType result;
1620 result.t = baseEnv(env)->ExceptionOccurred(env);
1621 if (sc.Check(soa, false, "t", &result)) {
1622 return result.t;
1623 }
1624 }
1625 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001626 }
1627
1628 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001629 ScopedObjectAccess soa(env);
1630 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1631 JniValueType args[1] = {{.E = env}};
1632 if (sc.Check(soa, true, "E", args)) {
1633 JniValueType result;
1634 baseEnv(env)->ExceptionDescribe(env);
1635 result.V = nullptr;
1636 sc.Check(soa, false, "V", &result);
1637 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001638 }
1639
1640 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001641 ScopedObjectAccess soa(env);
1642 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1643 JniValueType args[1] = {{.E = env}};
1644 if (sc.Check(soa, true, "E", args)) {
1645 JniValueType result;
1646 baseEnv(env)->ExceptionClear(env);
1647 result.V = nullptr;
1648 sc.Check(soa, false, "V", &result);
1649 }
1650 }
1651
1652 static jboolean ExceptionCheck(JNIEnv* env) {
1653 ScopedObjectAccess soa(env);
1654 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1655 JniValueType args[1] = {{.E = env}};
1656 if (sc.Check(soa, true, "E", args)) {
1657 JniValueType result;
1658 result.b = baseEnv(env)->ExceptionCheck(env);
1659 if (sc.Check(soa, false, "b", &result)) {
1660 return result.b;
1661 }
1662 }
1663 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001664 }
1665
1666 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001667 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1668 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1669 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001670 ScopedObjectAccess soa(env);
1671 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1672 JniValueType args[2] = {{.E = env}, {.u = msg}};
1673 if (sc.Check(soa, true, "Eu", args)) {
1674 JniValueType result;
1675 baseEnv(env)->FatalError(env, msg);
1676 // Unreachable.
1677 result.V = nullptr;
1678 sc.Check(soa, false, "V", &result);
1679 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001680 }
1681
1682 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001683 ScopedObjectAccess soa(env);
1684 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1685 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1686 if (sc.Check(soa, true, "EI", args)) {
1687 JniValueType result;
1688 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1689 if (sc.Check(soa, false, "i", &result)) {
1690 return result.i;
1691 }
1692 }
1693 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001694 }
1695
1696 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001697 ScopedObjectAccess soa(env);
1698 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1699 JniValueType args[2] = {{.E = env}, {.L = res}};
1700 if (sc.Check(soa, true, "EL", args)) {
1701 JniValueType result;
1702 result.L = baseEnv(env)->PopLocalFrame(env, res);
1703 sc.Check(soa, false, "L", &result);
1704 return result.L;
1705 }
1706 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001707 }
1708
1709 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001710 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001711 }
1712
Ian Rogers68d8b422014-07-17 11:09:10 -07001713 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1714 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001715 }
1716
1717 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001718 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001719 }
1720
Ian Rogers68d8b422014-07-17 11:09:10 -07001721 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1722 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001723 }
1724
Ian Rogers68d8b422014-07-17 11:09:10 -07001725 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1726 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1727 }
1728
1729 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1730 DeleteRef(__FUNCTION__, env, obj, kLocal);
1731 }
1732
1733 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1734 ScopedObjectAccess soa(env);
1735 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1736 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1737 if (sc.Check(soa, true, "EI", args)) {
1738 JniValueType result;
1739 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1740 if (sc.Check(soa, false, "i", &result)) {
1741 return result.i;
1742 }
1743 }
1744 return JNI_ERR;
1745 }
1746
1747 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1748 ScopedObjectAccess soa(env);
1749 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1750 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1751 if (sc.Check(soa, true, "ELL", args)) {
1752 JniValueType result;
1753 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1754 if (sc.Check(soa, false, "b", &result)) {
1755 return result.b;
1756 }
1757 }
1758 return JNI_FALSE;
1759 }
1760
1761 static jobject AllocObject(JNIEnv* env, jclass c) {
1762 ScopedObjectAccess soa(env);
1763 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1764 JniValueType args[2] = {{.E = env}, {.c = c}};
1765 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1766 JniValueType result;
1767 result.L = baseEnv(env)->AllocObject(env, c);
1768 if (sc.Check(soa, false, "L", &result)) {
1769 return result.L;
1770 }
1771 }
1772 return nullptr;
1773 }
1774
1775 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1776 ScopedObjectAccess soa(env);
1777 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1778 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
1779 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
1780 sc.CheckConstructor(soa, mid)) {
1781 JniValueType result;
1782 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
1783 if (sc.Check(soa, false, "L", &result)) {
1784 return result.L;
1785 }
1786 }
1787 return nullptr;
1788 }
1789
1790 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1791 va_list args;
1792 va_start(args, mid);
1793 jobject result = NewObjectV(env, c, mid, args);
1794 va_end(args);
1795 return result;
1796 }
1797
1798 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
1799 ScopedObjectAccess soa(env);
1800 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1801 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
1802 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
1803 sc.CheckConstructor(soa, mid)) {
1804 JniValueType result;
1805 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
1806 if (sc.Check(soa, false, "L", &result)) {
1807 return result.L;
1808 }
1809 }
1810 return nullptr;
1811 }
1812
1813 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1814 ScopedObjectAccess soa(env);
1815 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1816 JniValueType args[2] = {{.E = env}, {.L = obj}};
1817 if (sc.Check(soa, true, "EL", args)) {
1818 JniValueType result;
1819 result.c = baseEnv(env)->GetObjectClass(env, obj);
1820 if (sc.Check(soa, false, "c", &result)) {
1821 return result.c;
1822 }
1823 }
1824 return nullptr;
1825 }
1826
1827 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1828 ScopedObjectAccess soa(env);
1829 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1830 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
1831 if (sc.Check(soa, true, "ELc", args)) {
1832 JniValueType result;
1833 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
1834 if (sc.Check(soa, false, "b", &result)) {
1835 return result.b;
1836 }
1837 }
1838 return JNI_FALSE;
1839 }
1840
1841 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1842 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
1843 }
1844
1845 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1846 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
1847 }
1848
1849 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1850 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
1851 }
1852
1853 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1854 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
1855 }
1856
1857#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
1858 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1859 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
1860 } \
1861 \
1862 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1863 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
1864 } \
1865 \
1866 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
1867 JniValueType value; \
1868 value.shorty = v; \
1869 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
1870 } \
1871 \
1872 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
1873 JniValueType value; \
1874 value.shorty = v; \
1875 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
1876 }
1877
1878 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
1879 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
1880 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
1881 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
1882 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
1883 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
1884 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
1885 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
1886 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
1887#undef FIELD_ACCESSORS
1888
1889 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
1890 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1891 }
1892
1893 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1894 jvalue* vargs) {
1895 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1896 }
1897
1898 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
1899 CallMethodA(__FUNCTION__, env, c, nullptr, mid, vargs, Primitive::kPrimVoid, kStatic);
1900 }
1901
1902 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
1903 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1904 }
1905
1906 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1907 va_list vargs) {
1908 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1909 }
1910
1911 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1912 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1913 }
1914
1915 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1916 va_list vargs;
1917 va_start(vargs, mid);
1918 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1919 va_end(vargs);
1920 }
1921
1922 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
1923 va_list vargs;
1924 va_start(vargs, mid);
1925 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1926 va_end(vargs);
1927 }
1928
1929 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
1930 va_list vargs;
1931 va_start(vargs, mid);
1932 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1933 va_end(vargs);
1934 }
1935
1936#define CALL(rtype, name, ptype, shorty) \
1937 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
1938 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1939 } \
1940 \
1941 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1942 jvalue* vargs) { \
1943 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1944 } \
1945 \
1946 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
1947 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1948 } \
1949 \
1950 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
1951 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1952 } \
1953 \
1954 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1955 va_list vargs) { \
1956 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1957 } \
1958 \
1959 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
1960 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1961 } \
1962 \
1963 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
1964 va_list vargs; \
1965 va_start(vargs, mid); \
1966 rtype result = \
1967 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1968 va_end(vargs); \
1969 return result; \
1970 } \
1971 \
1972 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1973 ...) { \
1974 va_list vargs; \
1975 va_start(vargs, mid); \
1976 rtype result = \
1977 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1978 va_end(vargs); \
1979 return result; \
1980 } \
1981 \
1982 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
1983 va_list vargs; \
1984 va_start(vargs, mid); \
1985 rtype result = \
1986 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1987 va_end(vargs); \
1988 return result; \
1989 }
1990
1991 CALL(jobject, Object, Primitive::kPrimNot, L)
1992 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
1993 CALL(jbyte, Byte, Primitive::kPrimByte, B)
1994 CALL(jchar, Char, Primitive::kPrimChar, C)
1995 CALL(jshort, Short, Primitive::kPrimShort, S)
1996 CALL(jint, Int, Primitive::kPrimInt, I)
1997 CALL(jlong, Long, Primitive::kPrimLong, J)
1998 CALL(jfloat, Float, Primitive::kPrimFloat, F)
1999 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2000#undef CALL
2001
2002 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2003 ScopedObjectAccess soa(env);
2004 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2005 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2006 if (sc.Check(soa, true, "Epz", args)) {
2007 JniValueType result;
2008 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2009 if (sc.Check(soa, false, "s", &result)) {
2010 return result.s;
2011 }
2012 }
2013 return nullptr;
2014 }
2015
2016 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2017 ScopedObjectAccess soa(env);
2018 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2019 JniValueType args[2] = {{.E = env}, {.u = chars}};
2020 if (sc.Check(soa, true, "Eu", args)) {
2021 JniValueType result;
2022 // TODO: stale? show pointer and truncate string.
2023 result.s = baseEnv(env)->NewStringUTF(env, chars);
2024 if (sc.Check(soa, false, "s", &result)) {
2025 return result.s;
2026 }
2027 }
2028 return nullptr;
2029 }
2030
2031 static jsize GetStringLength(JNIEnv* env, jstring string) {
2032 ScopedObjectAccess soa(env);
2033 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2034 JniValueType args[2] = {{.E = env}, {.s = string}};
2035 if (sc.Check(soa, true, "Es", args)) {
2036 JniValueType result;
2037 result.z = baseEnv(env)->GetStringLength(env, string);
2038 if (sc.Check(soa, false, "z", &result)) {
2039 return result.z;
2040 }
2041 }
2042 return JNI_ERR;
2043 }
2044
2045 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2046 ScopedObjectAccess soa(env);
2047 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2048 JniValueType args[2] = {{.E = env}, {.s = string}};
2049 if (sc.Check(soa, true, "Es", args)) {
2050 JniValueType result;
2051 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2052 if (sc.Check(soa, false, "z", &result)) {
2053 return result.z;
2054 }
2055 }
2056 return JNI_ERR;
2057 }
2058
2059 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2060 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2061 is_copy, false, false));
2062 }
2063
2064 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2065 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2066 is_copy, true, false));
2067 }
2068
2069 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2070 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2071 is_copy, false, true));
2072 }
2073
2074 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2075 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2076 }
2077
2078 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2079 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2080 }
2081
2082 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2083 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2084 }
2085
2086 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2087 ScopedObjectAccess soa(env);
2088 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2089 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2090 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2091 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2092 if (sc.Check(soa, true, "EsIIp", args)) {
2093 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2094 JniValueType result;
2095 result.V = nullptr;
2096 sc.Check(soa, false, "V", &result);
2097 }
2098 }
2099
2100 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2101 ScopedObjectAccess soa(env);
2102 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2103 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2104 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2105 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2106 if (sc.Check(soa, true, "EsIIp", args)) {
2107 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2108 JniValueType result;
2109 result.V = nullptr;
2110 sc.Check(soa, false, "V", &result);
2111 }
2112 }
2113
2114 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2115 ScopedObjectAccess soa(env);
2116 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2117 JniValueType args[2] = {{.E = env}, {.a = array}};
2118 if (sc.Check(soa, true, "Ea", args)) {
2119 JniValueType result;
2120 result.z = baseEnv(env)->GetArrayLength(env, array);
2121 if (sc.Check(soa, false, "z", &result)) {
2122 return result.z;
2123 }
2124 }
2125 return JNI_ERR;
2126 }
2127
2128 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2129 jobject initial_element) {
2130 ScopedObjectAccess soa(env);
2131 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2132 JniValueType args[4] =
2133 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2134 if (sc.Check(soa, true, "EzcL", args)) {
2135 JniValueType result;
2136 // Note: assignability tests of initial_element are done in the base implementation.
2137 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2138 if (sc.Check(soa, false, "a", &result)) {
2139 return down_cast<jobjectArray>(result.a);
2140 }
2141 }
2142 return nullptr;
2143 }
2144
2145 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2146 ScopedObjectAccess soa(env);
2147 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2148 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2149 if (sc.Check(soa, true, "Eaz", args)) {
2150 JniValueType result;
2151 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2152 if (sc.Check(soa, false, "L", &result)) {
2153 return result.L;
2154 }
2155 }
2156 return nullptr;
2157 }
2158
2159 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2160 ScopedObjectAccess soa(env);
2161 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2162 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2163 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2164 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2165 // in ArrayStoreExceptions.
2166 if (sc.Check(soa, true, "EaIL", args)) {
2167 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2168 JniValueType result;
2169 result.V = nullptr;
2170 sc.Check(soa, false, "V", &result);
2171 }
2172 }
2173
2174 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2175 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2176 Primitive::kPrimBoolean));
2177 }
2178
2179 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2180 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2181 Primitive::kPrimByte));
2182 }
2183
2184 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2185 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2186 Primitive::kPrimChar));
2187 }
2188
2189 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2190 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2191 Primitive::kPrimShort));
2192 }
2193
2194 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2195 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2196 }
2197
2198 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2199 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2200 Primitive::kPrimLong));
2201 }
2202
2203 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2204 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2205 Primitive::kPrimFloat));
2206 }
2207
2208 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2209 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2210 Primitive::kPrimDouble));
2211 }
2212
2213#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2214 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
2215 return reinterpret_cast<ctype*>( \
2216 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2217 } \
2218 \
2219 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
2220 jint mode) { \
2221 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2222 } \
2223 \
2224 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2225 ctype* buf) { \
2226 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2227 } \
2228 \
2229 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2230 const ctype* buf) { \
2231 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2232 }
2233
2234 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2235 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2236 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2237 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2238 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2239 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2240 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2241 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2242#undef PRIMITIVE_ARRAY_FUNCTIONS
2243
2244 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2245 ScopedObjectAccess soa(env);
2246 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2247 JniValueType args[2] = {{.E = env}, {.L = obj}};
2248 if (sc.Check(soa, true, "EL", args)) {
2249 JniValueType result;
2250 result.i = baseEnv(env)->MonitorEnter(env, obj);
2251 if (sc.Check(soa, false, "i", &result)) {
2252 return result.i;
2253 }
2254 }
2255 return JNI_ERR;
2256 }
2257
2258 static jint MonitorExit(JNIEnv* env, jobject obj) {
2259 ScopedObjectAccess soa(env);
2260 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2261 JniValueType args[2] = {{.E = env}, {.L = obj}};
2262 if (sc.Check(soa, true, "EL", args)) {
2263 JniValueType result;
2264 result.i = baseEnv(env)->MonitorExit(env, obj);
2265 if (sc.Check(soa, false, "i", &result)) {
2266 return result.i;
2267 }
2268 }
2269 return JNI_ERR;
2270 }
2271
2272 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2273 ScopedObjectAccess soa(env);
2274 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2275 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2276 if (sc.Check(soa, true, "Eap", args)) {
2277 JniValueType result;
2278 result.p = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2279 if (result.p != nullptr && soa.ForceCopy()) {
2280 result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
2281 }
2282 if (sc.Check(soa, false, "p", &result)) {
2283 return const_cast<void*>(result.p);
2284 }
2285 }
2286 return nullptr;
2287 }
2288
2289 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2290 ScopedObjectAccess soa(env);
2291 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2292 sc.CheckNonNull(carray);
2293 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2294 if (sc.Check(soa, true, "Eapr", args)) {
2295 if (soa.ForceCopy()) {
2296 GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
2297 }
2298 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2299 JniValueType result;
2300 result.V = nullptr;
2301 sc.Check(soa, false, "V", &result);
2302 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002303 }
2304
2305 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002306 ScopedObjectAccess soa(env);
2307 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2308 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2309 if (sc.Check(soa, true, "EpJ", args)) {
2310 JniValueType result;
2311 // Note: the validity of address and capacity are checked in the base implementation.
2312 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2313 if (sc.Check(soa, false, "L", &result)) {
2314 return result.L;
2315 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002316 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002317 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002318 }
2319
2320 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002321 ScopedObjectAccess soa(env);
2322 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2323 JniValueType args[2] = {{.E = env}, {.L = buf}};
2324 if (sc.Check(soa, true, "EL", args)) {
2325 JniValueType result;
2326 // Note: this is implemented in the base environment by a GetLongField which will sanity
2327 // check the type of buf in GetLongField above.
2328 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2329 if (sc.Check(soa, false, "p", &result)) {
2330 return const_cast<void*>(result.p);
2331 }
2332 }
2333 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002334 }
2335
2336 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002337 ScopedObjectAccess soa(env);
2338 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2339 JniValueType args[2] = {{.E = env}, {.L = buf}};
2340 if (sc.Check(soa, true, "EL", args)) {
2341 JniValueType result;
2342 // Note: this is implemented in the base environment by a GetIntField which will sanity
2343 // check the type of buf in GetIntField above.
2344 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2345 if (sc.Check(soa, false, "J", &result)) {
2346 return result.J;
2347 }
2348 }
2349 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002350 }
2351
2352 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002353 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2354 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2355 }
2356
2357 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002358 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2359 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002360
2361 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2362 ScopedObjectAccess soa(env);
2363 ScopedCheck sc(kFlag_Default, function_name);
2364 JniValueType args[2] = {{.E = env}, {.L = obj}};
2365 if (sc.Check(soa, true, "EL", args)) {
2366 JniValueType result;
2367 switch (kind) {
2368 case kGlobal:
2369 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2370 break;
2371 case kLocal:
2372 result.L = baseEnv(env)->NewLocalRef(env, obj);
2373 break;
2374 case kWeakGlobal:
2375 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2376 break;
2377 default:
2378 LOG(FATAL) << "Unexpected reference kind: " << kind;
2379 }
2380 if (sc.Check(soa, false, "L", &result)) {
2381 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
2382 DCHECK(sc.CheckReferenceKind(kind, soa.Vm(), soa.Self(), result.L));
2383 return result.L;
2384 }
2385 }
2386 return nullptr;
2387 }
2388
2389 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2390 ScopedObjectAccess soa(env);
2391 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2392 JniValueType args[2] = {{.E = env}, {.L = obj}};
2393 sc.Check(soa, true, "EL", args);
2394 if (sc.CheckReferenceKind(kind, soa.Vm(), soa.Self(), obj)) {
2395 JniValueType result;
2396 switch (kind) {
2397 case kGlobal:
2398 baseEnv(env)->DeleteGlobalRef(env, obj);
2399 break;
2400 case kLocal:
2401 baseEnv(env)->DeleteLocalRef(env, obj);
2402 break;
2403 case kWeakGlobal:
2404 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2405 break;
2406 default:
2407 LOG(FATAL) << "Unexpected reference kind: " << kind;
2408 }
2409 result.V = nullptr;
2410 sc.Check(soa, false, "V", &result);
2411 }
2412 }
2413
2414 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2415 const char* name, const char* sig, bool is_static) {
2416 ScopedObjectAccess soa(env);
2417 ScopedCheck sc(kFlag_Default, function_name);
2418 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2419 if (sc.Check(soa, true, "Ecuu", args)) {
2420 JniValueType result;
2421 if (is_static) {
2422 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2423 } else {
2424 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2425 }
2426 if (sc.Check(soa, false, "m", &result)) {
2427 return result.m;
2428 }
2429 }
2430 return nullptr;
2431 }
2432
2433 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2434 const char* name, const char* sig, bool is_static) {
2435 ScopedObjectAccess soa(env);
2436 ScopedCheck sc(kFlag_Default, function_name);
2437 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2438 if (sc.Check(soa, true, "Ecuu", args)) {
2439 JniValueType result;
2440 if (is_static) {
2441 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2442 } else {
2443 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2444 }
2445 if (sc.Check(soa, false, "f", &result)) {
2446 return result.f;
2447 }
2448 }
2449 return nullptr;
2450 }
2451
2452 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2453 bool is_static, Primitive::Type type) {
2454 ScopedObjectAccess soa(env);
2455 ScopedCheck sc(kFlag_Default, function_name);
2456 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2457 JniValueType result;
2458 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2459 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2460 const char* result_check = nullptr;
2461 switch (type) {
2462 case Primitive::kPrimNot:
2463 if (is_static) {
2464 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2465 } else {
2466 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2467 }
2468 result_check = "L";
2469 break;
2470 case Primitive::kPrimBoolean:
2471 if (is_static) {
2472 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2473 } else {
2474 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2475 }
2476 result_check = "Z";
2477 break;
2478 case Primitive::kPrimByte:
2479 if (is_static) {
2480 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2481 } else {
2482 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2483 }
2484 result_check = "B";
2485 break;
2486 case Primitive::kPrimChar:
2487 if (is_static) {
2488 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2489 } else {
2490 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2491 }
2492 result_check = "C";
2493 break;
2494 case Primitive::kPrimShort:
2495 if (is_static) {
2496 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2497 } else {
2498 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2499 }
2500 result_check = "S";
2501 break;
2502 case Primitive::kPrimInt:
2503 if (is_static) {
2504 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2505 } else {
2506 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2507 }
2508 result_check = "I";
2509 break;
2510 case Primitive::kPrimLong:
2511 if (is_static) {
2512 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2513 } else {
2514 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2515 }
2516 result_check = "J";
2517 break;
2518 case Primitive::kPrimFloat:
2519 if (is_static) {
2520 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2521 } else {
2522 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2523 }
2524 result_check = "F";
2525 break;
2526 case Primitive::kPrimDouble:
2527 if (is_static) {
2528 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2529 } else {
2530 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2531 }
2532 result_check = "D";
2533 break;
2534 case Primitive::kPrimVoid:
2535 LOG(FATAL) << "Unexpected type: " << type;
2536 break;
2537 }
2538 if (sc.Check(soa, false, result_check, &result)) {
2539 return result;
2540 }
2541 }
2542 result.J = 0;
2543 return result;
2544 }
2545
2546 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2547 bool is_static, Primitive::Type type, JniValueType value) {
2548 ScopedObjectAccess soa(env);
2549 ScopedCheck sc(kFlag_Default, function_name);
2550 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2551 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2552 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2553 if (sc.Check(soa, true, sig, args) &&
2554 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2555 switch (type) {
2556 case Primitive::kPrimNot:
2557 if (is_static) {
2558 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2559 } else {
2560 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2561 }
2562 break;
2563 case Primitive::kPrimBoolean:
2564 if (is_static) {
2565 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2566 } else {
2567 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2568 }
2569 break;
2570 case Primitive::kPrimByte:
2571 if (is_static) {
2572 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2573 } else {
2574 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2575 }
2576 break;
2577 case Primitive::kPrimChar:
2578 if (is_static) {
2579 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2580 } else {
2581 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2582 }
2583 break;
2584 case Primitive::kPrimShort:
2585 if (is_static) {
2586 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2587 } else {
2588 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2589 }
2590 break;
2591 case Primitive::kPrimInt:
2592 if (is_static) {
2593 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2594 } else {
2595 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2596 }
2597 break;
2598 case Primitive::kPrimLong:
2599 if (is_static) {
2600 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2601 } else {
2602 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2603 }
2604 break;
2605 case Primitive::kPrimFloat:
2606 if (is_static) {
2607 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2608 } else {
2609 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2610 }
2611 break;
2612 case Primitive::kPrimDouble:
2613 if (is_static) {
2614 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2615 } else {
2616 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2617 }
2618 break;
2619 case Primitive::kPrimVoid:
2620 LOG(FATAL) << "Unexpected type: " << type;
2621 break;
2622 }
2623 JniValueType result;
2624 result.V = nullptr;
2625 sc.Check(soa, false, "V", &result);
2626 }
2627 }
2628
2629 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
2630 jclass c, jmethodID mid, InvokeType invoke)
2631 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2632 bool checked;
2633 switch (invoke) {
2634 case kVirtual: {
2635 DCHECK(c == nullptr);
2636 JniValueType args[3] = {{.E = env}, {.L = obj}, {.m = mid}};
2637 checked = sc.Check(soa, true, "ELm.", args);
2638 break;
2639 }
2640 case kDirect: {
2641 JniValueType args[4] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}};
2642 checked = sc.Check(soa, true, "ELcm.", args);
2643 break;
2644 }
2645 case kStatic: {
2646 DCHECK(obj == nullptr);
2647 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
2648 checked = sc.Check(soa, true, "Ecm.", args);
2649 break;
2650 }
2651 default:
2652 LOG(FATAL) << "Unexpected invoke: " << invoke;
2653 checked = false;
2654 break;
2655 }
2656 return checked;
2657 }
2658
2659 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2660 jmethodID mid, jvalue* vargs, Primitive::Type type,
2661 InvokeType invoke) {
2662 ScopedObjectAccess soa(env);
2663 ScopedCheck sc(kFlag_Default, function_name);
2664 JniValueType result;
2665 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2666 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2667 const char* result_check;
2668 switch (type) {
2669 case Primitive::kPrimNot:
2670 result_check = "L";
2671 switch (invoke) {
2672 case kVirtual:
2673 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2674 break;
2675 case kDirect:
2676 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2677 break;
2678 case kStatic:
2679 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2680 break;
2681 default:
2682 break;
2683 }
2684 break;
2685 case Primitive::kPrimBoolean:
2686 result_check = "Z";
2687 switch (invoke) {
2688 case kVirtual:
2689 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2690 break;
2691 case kDirect:
2692 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2693 break;
2694 case kStatic:
2695 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2696 break;
2697 default:
2698 break;
2699 }
2700 break;
2701 case Primitive::kPrimByte:
2702 result_check = "B";
2703 switch (invoke) {
2704 case kVirtual:
2705 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2706 break;
2707 case kDirect:
2708 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2709 break;
2710 case kStatic:
2711 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2712 break;
2713 default:
2714 break;
2715 }
2716 break;
2717 case Primitive::kPrimChar:
2718 result_check = "C";
2719 switch (invoke) {
2720 case kVirtual:
2721 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2722 break;
2723 case kDirect:
2724 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2725 break;
2726 case kStatic:
2727 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2728 break;
2729 default:
2730 break;
2731 }
2732 break;
2733 case Primitive::kPrimShort:
2734 result_check = "S";
2735 switch (invoke) {
2736 case kVirtual:
2737 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2738 break;
2739 case kDirect:
2740 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2741 break;
2742 case kStatic:
2743 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2744 break;
2745 default:
2746 break;
2747 }
2748 break;
2749 case Primitive::kPrimInt:
2750 result_check = "I";
2751 switch (invoke) {
2752 case kVirtual:
2753 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2754 break;
2755 case kDirect:
2756 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2757 break;
2758 case kStatic:
2759 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2760 break;
2761 default:
2762 break;
2763 }
2764 break;
2765 case Primitive::kPrimLong:
2766 result_check = "J";
2767 switch (invoke) {
2768 case kVirtual:
2769 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
2770 break;
2771 case kDirect:
2772 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
2773 break;
2774 case kStatic:
2775 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
2776 break;
2777 default:
2778 break;
2779 }
2780 break;
2781 case Primitive::kPrimFloat:
2782 result_check = "F";
2783 switch (invoke) {
2784 case kVirtual:
2785 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
2786 break;
2787 case kDirect:
2788 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
2789 break;
2790 case kStatic:
2791 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
2792 break;
2793 default:
2794 break;
2795 }
2796 break;
2797 case Primitive::kPrimDouble:
2798 result_check = "D";
2799 switch (invoke) {
2800 case kVirtual:
2801 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
2802 break;
2803 case kDirect:
2804 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
2805 break;
2806 case kStatic:
2807 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
2808 break;
2809 default:
2810 break;
2811 }
2812 break;
2813 case Primitive::kPrimVoid:
2814 result_check = "V";
2815 result.V = nullptr;
2816 switch (invoke) {
2817 case kVirtual:
2818 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
2819 break;
2820 case kDirect:
2821 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
2822 break;
2823 case kStatic:
2824 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
2825 break;
2826 default:
2827 LOG(FATAL) << "Unexpected invoke: " << invoke;
2828 }
2829 break;
2830 default:
2831 LOG(FATAL) << "Unexpected return type: " << type;
2832 result_check = nullptr;
2833 }
2834 if (sc.Check(soa, false, result_check, &result)) {
2835 return result;
2836 }
2837 }
2838 result.J = 0;
2839 return result;
2840 }
2841
2842 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2843 jmethodID mid, va_list vargs, Primitive::Type type,
2844 InvokeType invoke) {
2845 ScopedObjectAccess soa(env);
2846 ScopedCheck sc(kFlag_Default, function_name);
2847 JniValueType result;
2848 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2849 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2850 const char* result_check;
2851 switch (type) {
2852 case Primitive::kPrimNot:
2853 result_check = "L";
2854 switch (invoke) {
2855 case kVirtual:
2856 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
2857 break;
2858 case kDirect:
2859 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
2860 break;
2861 case kStatic:
2862 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
2863 break;
2864 default:
2865 LOG(FATAL) << "Unexpected invoke: " << invoke;
2866 }
2867 break;
2868 case Primitive::kPrimBoolean:
2869 result_check = "Z";
2870 switch (invoke) {
2871 case kVirtual:
2872 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
2873 break;
2874 case kDirect:
2875 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
2876 break;
2877 case kStatic:
2878 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
2879 break;
2880 default:
2881 LOG(FATAL) << "Unexpected invoke: " << invoke;
2882 }
2883 break;
2884 case Primitive::kPrimByte:
2885 result_check = "B";
2886 switch (invoke) {
2887 case kVirtual:
2888 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
2889 break;
2890 case kDirect:
2891 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
2892 break;
2893 case kStatic:
2894 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
2895 break;
2896 default:
2897 LOG(FATAL) << "Unexpected invoke: " << invoke;
2898 }
2899 break;
2900 case Primitive::kPrimChar:
2901 result_check = "C";
2902 switch (invoke) {
2903 case kVirtual:
2904 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
2905 break;
2906 case kDirect:
2907 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
2908 break;
2909 case kStatic:
2910 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
2911 break;
2912 default:
2913 LOG(FATAL) << "Unexpected invoke: " << invoke;
2914 }
2915 break;
2916 case Primitive::kPrimShort:
2917 result_check = "S";
2918 switch (invoke) {
2919 case kVirtual:
2920 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
2921 break;
2922 case kDirect:
2923 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
2924 break;
2925 case kStatic:
2926 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
2927 break;
2928 default:
2929 LOG(FATAL) << "Unexpected invoke: " << invoke;
2930 }
2931 break;
2932 case Primitive::kPrimInt:
2933 result_check = "I";
2934 switch (invoke) {
2935 case kVirtual:
2936 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
2937 break;
2938 case kDirect:
2939 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
2940 break;
2941 case kStatic:
2942 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
2943 break;
2944 default:
2945 LOG(FATAL) << "Unexpected invoke: " << invoke;
2946 }
2947 break;
2948 case Primitive::kPrimLong:
2949 result_check = "J";
2950 switch (invoke) {
2951 case kVirtual:
2952 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
2953 break;
2954 case kDirect:
2955 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
2956 break;
2957 case kStatic:
2958 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
2959 break;
2960 default:
2961 LOG(FATAL) << "Unexpected invoke: " << invoke;
2962 }
2963 break;
2964 case Primitive::kPrimFloat:
2965 result_check = "F";
2966 switch (invoke) {
2967 case kVirtual:
2968 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
2969 break;
2970 case kDirect:
2971 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
2972 break;
2973 case kStatic:
2974 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
2975 break;
2976 default:
2977 LOG(FATAL) << "Unexpected invoke: " << invoke;
2978 }
2979 break;
2980 case Primitive::kPrimDouble:
2981 result_check = "D";
2982 switch (invoke) {
2983 case kVirtual:
2984 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
2985 break;
2986 case kDirect:
2987 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
2988 break;
2989 case kStatic:
2990 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
2991 break;
2992 default:
2993 LOG(FATAL) << "Unexpected invoke: " << invoke;
2994 }
2995 break;
2996 case Primitive::kPrimVoid:
2997 result_check = "V";
2998 result.V = nullptr;
2999 switch (invoke) {
3000 case kVirtual:
3001 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3002 break;
3003 case kDirect:
3004 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3005 break;
3006 case kStatic:
3007 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3008 break;
3009 default:
3010 LOG(FATAL) << "Unexpected invoke: " << invoke;
3011 }
3012 break;
3013 default:
3014 LOG(FATAL) << "Unexpected return type: " << type;
3015 result_check = nullptr;
3016 }
3017 if (sc.Check(soa, false, result_check, &result)) {
3018 return result;
3019 }
3020 }
3021 result.J = 0;
3022 return result;
3023 }
3024
3025 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3026 jboolean* is_copy, bool utf, bool critical) {
3027 ScopedObjectAccess soa(env);
3028 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3029 ScopedCheck sc(flags, function_name);
3030 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3031 if (sc.Check(soa, true, "Esp", args)) {
3032 JniValueType result;
3033 if (utf) {
3034 CHECK(!critical);
3035 result.u = baseEnv(env)->GetStringUTFChars(env, string, is_copy);
3036 } else {
3037 if (critical) {
3038 result.p = baseEnv(env)->GetStringCritical(env, string, is_copy);
3039 } else {
3040 result.p = baseEnv(env)->GetStringChars(env, string, is_copy);
3041 }
3042 }
3043 // TODO: could we be smarter about not copying when local_is_copy?
3044 if (result.p != nullptr && soa.ForceCopy()) {
3045 if (utf) {
3046 size_t length_in_bytes = strlen(result.u) + 1;
3047 result.u =
3048 reinterpret_cast<const char*>(GuardedCopy::Create(result.u, length_in_bytes, false));
3049 } else {
3050 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3051 result.p =
3052 reinterpret_cast<const jchar*>(GuardedCopy::Create(result.p, length_in_bytes, false));
3053 }
3054 if (is_copy != nullptr) {
3055 *is_copy = JNI_TRUE;
3056 }
3057 }
3058 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3059 return utf ? result.u : result.p;
3060 }
3061 }
3062 return nullptr;
3063 }
3064
3065 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3066 const void* chars, bool utf, bool critical) {
3067 ScopedObjectAccess soa(env);
3068 int flags = kFlag_ExcepOkay | kFlag_Release;
3069 if (critical) {
3070 flags |= kFlag_CritRelease;
3071 }
3072 ScopedCheck sc(flags, function_name);
3073 sc.CheckNonNull(chars);
3074 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3075 if (force_copy_ok && soa.ForceCopy()) {
3076 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3077 }
3078 if (force_copy_ok) {
3079 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3080 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3081 if (utf) {
3082 CHECK(!critical);
3083 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3084 } else {
3085 if (critical) {
3086 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3087 } else {
3088 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3089 }
3090 }
3091 JniValueType result;
3092 sc.Check(soa, false, "V", &result);
3093 }
3094 }
3095 }
3096
3097 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3098 Primitive::Type type) {
3099 ScopedObjectAccess soa(env);
3100 ScopedCheck sc(kFlag_Default, __FUNCTION__);
3101 JniValueType args[2] = {{.E = env}, {.z = length}};
3102 if (sc.Check(soa, true, "Ez", args)) {
3103 JniValueType result;
3104 switch (type) {
3105 case Primitive::kPrimBoolean:
3106 result.a = baseEnv(env)->NewBooleanArray(env, length);
3107 break;
3108 case Primitive::kPrimByte:
3109 result.a = baseEnv(env)->NewByteArray(env, length);
3110 break;
3111 case Primitive::kPrimChar:
3112 result.a = baseEnv(env)->NewCharArray(env, length);
3113 break;
3114 case Primitive::kPrimShort:
3115 result.a = baseEnv(env)->NewShortArray(env, length);
3116 break;
3117 case Primitive::kPrimInt:
3118 result.a = baseEnv(env)->NewIntArray(env, length);
3119 break;
3120 case Primitive::kPrimLong:
3121 result.a = baseEnv(env)->NewLongArray(env, length);
3122 break;
3123 case Primitive::kPrimFloat:
3124 result.a = baseEnv(env)->NewFloatArray(env, length);
3125 break;
3126 case Primitive::kPrimDouble:
3127 result.a = baseEnv(env)->NewDoubleArray(env, length);
3128 break;
3129 default:
3130 LOG(FATAL) << "Unexpected primitive type: " << type;
3131 }
3132 if (sc.Check(soa, false, "a", &result)) {
3133 return result.a;
3134 }
3135 }
3136 return nullptr;
3137 }
3138
3139 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3140 JNIEnv* env, jarray array, jboolean* is_copy) {
3141 ScopedObjectAccess soa(env);
3142 ScopedCheck sc(kFlag_Default, function_name);
3143 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3144 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3145 JniValueType result;
3146 switch (type) {
3147 case Primitive::kPrimBoolean:
3148 result.p = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3149 is_copy);
3150 break;
3151 case Primitive::kPrimByte:
3152 result.p = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array),
3153 is_copy);
3154 break;
3155 case Primitive::kPrimChar:
3156 result.p = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array),
3157 is_copy);
3158 break;
3159 case Primitive::kPrimShort:
3160 result.p = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array),
3161 is_copy);
3162 break;
3163 case Primitive::kPrimInt:
3164 result.p = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
3165 break;
3166 case Primitive::kPrimLong:
3167 result.p = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array),
3168 is_copy);
3169 break;
3170 case Primitive::kPrimFloat:
3171 result.p = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array),
3172 is_copy);
3173 break;
3174 case Primitive::kPrimDouble:
3175 result.p = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3176 is_copy);
3177 break;
3178 default:
3179 LOG(FATAL) << "Unexpected primitive type: " << type;
3180 }
3181 if (result.p != nullptr && soa.ForceCopy()) {
3182 result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
3183 if (is_copy != nullptr) {
3184 *is_copy = JNI_TRUE;
3185 }
3186 }
3187 if (sc.Check(soa, false, "p", &result)) {
3188 return const_cast<void*>(result.p);
3189 }
3190 }
3191 return nullptr;
3192 }
3193
3194 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3195 JNIEnv* env, jarray array, void* elems, jint mode) {
3196 ScopedObjectAccess soa(env);
3197 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3198 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3199 if (soa.ForceCopy()) {
3200 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3201 }
3202 if (!soa.ForceCopy() || elems != nullptr) {
3203 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3204 if (sc.Check(soa, true, "Eapr", args)) {
3205 switch (type) {
3206 case Primitive::kPrimBoolean:
3207 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3208 reinterpret_cast<jboolean*>(elems), mode);
3209 break;
3210 case Primitive::kPrimByte:
3211 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3212 reinterpret_cast<jbyte*>(elems), mode);
3213 break;
3214 case Primitive::kPrimChar:
3215 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3216 reinterpret_cast<jchar*>(elems), mode);
3217 break;
3218 case Primitive::kPrimShort:
3219 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3220 reinterpret_cast<jshort*>(elems), mode);
3221 break;
3222 case Primitive::kPrimInt:
3223 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3224 reinterpret_cast<jint*>(elems), mode);
3225 break;
3226 case Primitive::kPrimLong:
3227 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3228 reinterpret_cast<jlong*>(elems), mode);
3229 break;
3230 case Primitive::kPrimFloat:
3231 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3232 reinterpret_cast<jfloat*>(elems), mode);
3233 break;
3234 case Primitive::kPrimDouble:
3235 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3236 reinterpret_cast<jdouble*>(elems), mode);
3237 break;
3238 default:
3239 LOG(FATAL) << "Unexpected primitive type: " << type;
3240 }
3241 JniValueType result;
3242 result.V = nullptr;
3243 sc.Check(soa, false, "V", &result);
3244 }
3245 }
3246 }
3247 }
3248
3249 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3250 jarray array, jsize start, jsize len, void* buf) {
3251 ScopedObjectAccess soa(env);
3252 ScopedCheck sc(kFlag_Default, function_name);
3253 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3254 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3255 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3256 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3257 switch (type) {
3258 case Primitive::kPrimBoolean:
3259 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3260 reinterpret_cast<jboolean*>(buf));
3261 break;
3262 case Primitive::kPrimByte:
3263 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3264 reinterpret_cast<jbyte*>(buf));
3265 break;
3266 case Primitive::kPrimChar:
3267 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3268 reinterpret_cast<jchar*>(buf));
3269 break;
3270 case Primitive::kPrimShort:
3271 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3272 reinterpret_cast<jshort*>(buf));
3273 break;
3274 case Primitive::kPrimInt:
3275 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3276 reinterpret_cast<jint*>(buf));
3277 break;
3278 case Primitive::kPrimLong:
3279 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3280 reinterpret_cast<jlong*>(buf));
3281 break;
3282 case Primitive::kPrimFloat:
3283 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3284 reinterpret_cast<jfloat*>(buf));
3285 break;
3286 case Primitive::kPrimDouble:
3287 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3288 reinterpret_cast<jdouble*>(buf));
3289 break;
3290 default:
3291 LOG(FATAL) << "Unexpected primitive type: " << type;
3292 }
3293 JniValueType result;
3294 result.V = nullptr;
3295 sc.Check(soa, false, "V", &result);
3296 }
3297 }
3298
3299 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3300 jarray array, jsize start, jsize len, const void* buf) {
3301 ScopedObjectAccess soa(env);
3302 ScopedCheck sc(kFlag_Default, function_name);
3303 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3304 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3305 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3306 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3307 switch (type) {
3308 case Primitive::kPrimBoolean:
3309 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3310 reinterpret_cast<const jboolean*>(buf));
3311 break;
3312 case Primitive::kPrimByte:
3313 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3314 reinterpret_cast<const jbyte*>(buf));
3315 break;
3316 case Primitive::kPrimChar:
3317 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3318 reinterpret_cast<const jchar*>(buf));
3319 break;
3320 case Primitive::kPrimShort:
3321 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3322 reinterpret_cast<const jshort*>(buf));
3323 break;
3324 case Primitive::kPrimInt:
3325 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3326 reinterpret_cast<const jint*>(buf));
3327 break;
3328 case Primitive::kPrimLong:
3329 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3330 reinterpret_cast<const jlong*>(buf));
3331 break;
3332 case Primitive::kPrimFloat:
3333 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3334 reinterpret_cast<const jfloat*>(buf));
3335 break;
3336 case Primitive::kPrimDouble:
3337 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3338 reinterpret_cast<const jdouble*>(buf));
3339 break;
3340 default:
3341 LOG(FATAL) << "Unexpected primitive type: " << type;
3342 }
3343 JniValueType result;
3344 result.V = nullptr;
3345 sc.Check(soa, false, "V", &result);
3346 }
3347 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003348};
3349
3350const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003351 nullptr, // reserved0.
3352 nullptr, // reserved1.
3353 nullptr, // reserved2.
3354 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003355 CheckJNI::GetVersion,
3356 CheckJNI::DefineClass,
3357 CheckJNI::FindClass,
3358 CheckJNI::FromReflectedMethod,
3359 CheckJNI::FromReflectedField,
3360 CheckJNI::ToReflectedMethod,
3361 CheckJNI::GetSuperclass,
3362 CheckJNI::IsAssignableFrom,
3363 CheckJNI::ToReflectedField,
3364 CheckJNI::Throw,
3365 CheckJNI::ThrowNew,
3366 CheckJNI::ExceptionOccurred,
3367 CheckJNI::ExceptionDescribe,
3368 CheckJNI::ExceptionClear,
3369 CheckJNI::FatalError,
3370 CheckJNI::PushLocalFrame,
3371 CheckJNI::PopLocalFrame,
3372 CheckJNI::NewGlobalRef,
3373 CheckJNI::DeleteGlobalRef,
3374 CheckJNI::DeleteLocalRef,
3375 CheckJNI::IsSameObject,
3376 CheckJNI::NewLocalRef,
3377 CheckJNI::EnsureLocalCapacity,
3378 CheckJNI::AllocObject,
3379 CheckJNI::NewObject,
3380 CheckJNI::NewObjectV,
3381 CheckJNI::NewObjectA,
3382 CheckJNI::GetObjectClass,
3383 CheckJNI::IsInstanceOf,
3384 CheckJNI::GetMethodID,
3385 CheckJNI::CallObjectMethod,
3386 CheckJNI::CallObjectMethodV,
3387 CheckJNI::CallObjectMethodA,
3388 CheckJNI::CallBooleanMethod,
3389 CheckJNI::CallBooleanMethodV,
3390 CheckJNI::CallBooleanMethodA,
3391 CheckJNI::CallByteMethod,
3392 CheckJNI::CallByteMethodV,
3393 CheckJNI::CallByteMethodA,
3394 CheckJNI::CallCharMethod,
3395 CheckJNI::CallCharMethodV,
3396 CheckJNI::CallCharMethodA,
3397 CheckJNI::CallShortMethod,
3398 CheckJNI::CallShortMethodV,
3399 CheckJNI::CallShortMethodA,
3400 CheckJNI::CallIntMethod,
3401 CheckJNI::CallIntMethodV,
3402 CheckJNI::CallIntMethodA,
3403 CheckJNI::CallLongMethod,
3404 CheckJNI::CallLongMethodV,
3405 CheckJNI::CallLongMethodA,
3406 CheckJNI::CallFloatMethod,
3407 CheckJNI::CallFloatMethodV,
3408 CheckJNI::CallFloatMethodA,
3409 CheckJNI::CallDoubleMethod,
3410 CheckJNI::CallDoubleMethodV,
3411 CheckJNI::CallDoubleMethodA,
3412 CheckJNI::CallVoidMethod,
3413 CheckJNI::CallVoidMethodV,
3414 CheckJNI::CallVoidMethodA,
3415 CheckJNI::CallNonvirtualObjectMethod,
3416 CheckJNI::CallNonvirtualObjectMethodV,
3417 CheckJNI::CallNonvirtualObjectMethodA,
3418 CheckJNI::CallNonvirtualBooleanMethod,
3419 CheckJNI::CallNonvirtualBooleanMethodV,
3420 CheckJNI::CallNonvirtualBooleanMethodA,
3421 CheckJNI::CallNonvirtualByteMethod,
3422 CheckJNI::CallNonvirtualByteMethodV,
3423 CheckJNI::CallNonvirtualByteMethodA,
3424 CheckJNI::CallNonvirtualCharMethod,
3425 CheckJNI::CallNonvirtualCharMethodV,
3426 CheckJNI::CallNonvirtualCharMethodA,
3427 CheckJNI::CallNonvirtualShortMethod,
3428 CheckJNI::CallNonvirtualShortMethodV,
3429 CheckJNI::CallNonvirtualShortMethodA,
3430 CheckJNI::CallNonvirtualIntMethod,
3431 CheckJNI::CallNonvirtualIntMethodV,
3432 CheckJNI::CallNonvirtualIntMethodA,
3433 CheckJNI::CallNonvirtualLongMethod,
3434 CheckJNI::CallNonvirtualLongMethodV,
3435 CheckJNI::CallNonvirtualLongMethodA,
3436 CheckJNI::CallNonvirtualFloatMethod,
3437 CheckJNI::CallNonvirtualFloatMethodV,
3438 CheckJNI::CallNonvirtualFloatMethodA,
3439 CheckJNI::CallNonvirtualDoubleMethod,
3440 CheckJNI::CallNonvirtualDoubleMethodV,
3441 CheckJNI::CallNonvirtualDoubleMethodA,
3442 CheckJNI::CallNonvirtualVoidMethod,
3443 CheckJNI::CallNonvirtualVoidMethodV,
3444 CheckJNI::CallNonvirtualVoidMethodA,
3445 CheckJNI::GetFieldID,
3446 CheckJNI::GetObjectField,
3447 CheckJNI::GetBooleanField,
3448 CheckJNI::GetByteField,
3449 CheckJNI::GetCharField,
3450 CheckJNI::GetShortField,
3451 CheckJNI::GetIntField,
3452 CheckJNI::GetLongField,
3453 CheckJNI::GetFloatField,
3454 CheckJNI::GetDoubleField,
3455 CheckJNI::SetObjectField,
3456 CheckJNI::SetBooleanField,
3457 CheckJNI::SetByteField,
3458 CheckJNI::SetCharField,
3459 CheckJNI::SetShortField,
3460 CheckJNI::SetIntField,
3461 CheckJNI::SetLongField,
3462 CheckJNI::SetFloatField,
3463 CheckJNI::SetDoubleField,
3464 CheckJNI::GetStaticMethodID,
3465 CheckJNI::CallStaticObjectMethod,
3466 CheckJNI::CallStaticObjectMethodV,
3467 CheckJNI::CallStaticObjectMethodA,
3468 CheckJNI::CallStaticBooleanMethod,
3469 CheckJNI::CallStaticBooleanMethodV,
3470 CheckJNI::CallStaticBooleanMethodA,
3471 CheckJNI::CallStaticByteMethod,
3472 CheckJNI::CallStaticByteMethodV,
3473 CheckJNI::CallStaticByteMethodA,
3474 CheckJNI::CallStaticCharMethod,
3475 CheckJNI::CallStaticCharMethodV,
3476 CheckJNI::CallStaticCharMethodA,
3477 CheckJNI::CallStaticShortMethod,
3478 CheckJNI::CallStaticShortMethodV,
3479 CheckJNI::CallStaticShortMethodA,
3480 CheckJNI::CallStaticIntMethod,
3481 CheckJNI::CallStaticIntMethodV,
3482 CheckJNI::CallStaticIntMethodA,
3483 CheckJNI::CallStaticLongMethod,
3484 CheckJNI::CallStaticLongMethodV,
3485 CheckJNI::CallStaticLongMethodA,
3486 CheckJNI::CallStaticFloatMethod,
3487 CheckJNI::CallStaticFloatMethodV,
3488 CheckJNI::CallStaticFloatMethodA,
3489 CheckJNI::CallStaticDoubleMethod,
3490 CheckJNI::CallStaticDoubleMethodV,
3491 CheckJNI::CallStaticDoubleMethodA,
3492 CheckJNI::CallStaticVoidMethod,
3493 CheckJNI::CallStaticVoidMethodV,
3494 CheckJNI::CallStaticVoidMethodA,
3495 CheckJNI::GetStaticFieldID,
3496 CheckJNI::GetStaticObjectField,
3497 CheckJNI::GetStaticBooleanField,
3498 CheckJNI::GetStaticByteField,
3499 CheckJNI::GetStaticCharField,
3500 CheckJNI::GetStaticShortField,
3501 CheckJNI::GetStaticIntField,
3502 CheckJNI::GetStaticLongField,
3503 CheckJNI::GetStaticFloatField,
3504 CheckJNI::GetStaticDoubleField,
3505 CheckJNI::SetStaticObjectField,
3506 CheckJNI::SetStaticBooleanField,
3507 CheckJNI::SetStaticByteField,
3508 CheckJNI::SetStaticCharField,
3509 CheckJNI::SetStaticShortField,
3510 CheckJNI::SetStaticIntField,
3511 CheckJNI::SetStaticLongField,
3512 CheckJNI::SetStaticFloatField,
3513 CheckJNI::SetStaticDoubleField,
3514 CheckJNI::NewString,
3515 CheckJNI::GetStringLength,
3516 CheckJNI::GetStringChars,
3517 CheckJNI::ReleaseStringChars,
3518 CheckJNI::NewStringUTF,
3519 CheckJNI::GetStringUTFLength,
3520 CheckJNI::GetStringUTFChars,
3521 CheckJNI::ReleaseStringUTFChars,
3522 CheckJNI::GetArrayLength,
3523 CheckJNI::NewObjectArray,
3524 CheckJNI::GetObjectArrayElement,
3525 CheckJNI::SetObjectArrayElement,
3526 CheckJNI::NewBooleanArray,
3527 CheckJNI::NewByteArray,
3528 CheckJNI::NewCharArray,
3529 CheckJNI::NewShortArray,
3530 CheckJNI::NewIntArray,
3531 CheckJNI::NewLongArray,
3532 CheckJNI::NewFloatArray,
3533 CheckJNI::NewDoubleArray,
3534 CheckJNI::GetBooleanArrayElements,
3535 CheckJNI::GetByteArrayElements,
3536 CheckJNI::GetCharArrayElements,
3537 CheckJNI::GetShortArrayElements,
3538 CheckJNI::GetIntArrayElements,
3539 CheckJNI::GetLongArrayElements,
3540 CheckJNI::GetFloatArrayElements,
3541 CheckJNI::GetDoubleArrayElements,
3542 CheckJNI::ReleaseBooleanArrayElements,
3543 CheckJNI::ReleaseByteArrayElements,
3544 CheckJNI::ReleaseCharArrayElements,
3545 CheckJNI::ReleaseShortArrayElements,
3546 CheckJNI::ReleaseIntArrayElements,
3547 CheckJNI::ReleaseLongArrayElements,
3548 CheckJNI::ReleaseFloatArrayElements,
3549 CheckJNI::ReleaseDoubleArrayElements,
3550 CheckJNI::GetBooleanArrayRegion,
3551 CheckJNI::GetByteArrayRegion,
3552 CheckJNI::GetCharArrayRegion,
3553 CheckJNI::GetShortArrayRegion,
3554 CheckJNI::GetIntArrayRegion,
3555 CheckJNI::GetLongArrayRegion,
3556 CheckJNI::GetFloatArrayRegion,
3557 CheckJNI::GetDoubleArrayRegion,
3558 CheckJNI::SetBooleanArrayRegion,
3559 CheckJNI::SetByteArrayRegion,
3560 CheckJNI::SetCharArrayRegion,
3561 CheckJNI::SetShortArrayRegion,
3562 CheckJNI::SetIntArrayRegion,
3563 CheckJNI::SetLongArrayRegion,
3564 CheckJNI::SetFloatArrayRegion,
3565 CheckJNI::SetDoubleArrayRegion,
3566 CheckJNI::RegisterNatives,
3567 CheckJNI::UnregisterNatives,
3568 CheckJNI::MonitorEnter,
3569 CheckJNI::MonitorExit,
3570 CheckJNI::GetJavaVM,
3571 CheckJNI::GetStringRegion,
3572 CheckJNI::GetStringUTFRegion,
3573 CheckJNI::GetPrimitiveArrayCritical,
3574 CheckJNI::ReleasePrimitiveArrayCritical,
3575 CheckJNI::GetStringCritical,
3576 CheckJNI::ReleaseStringCritical,
3577 CheckJNI::NewWeakGlobalRef,
3578 CheckJNI::DeleteWeakGlobalRef,
3579 CheckJNI::ExceptionCheck,
3580 CheckJNI::NewDirectByteBuffer,
3581 CheckJNI::GetDirectBufferAddress,
3582 CheckJNI::GetDirectBufferCapacity,
3583 CheckJNI::GetObjectRefType,
3584};
3585
3586const JNINativeInterface* GetCheckJniNativeInterface() {
3587 return &gCheckNativeInterface;
3588}
3589
3590class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003591 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003592 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003593 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3594 JniValueType args[1] = {{.v = vm}};
3595 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3596 JniValueType result;
3597 result.i = BaseVm(vm)->DestroyJavaVM(vm);
3598 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3599 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003600 }
3601
3602 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003603 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3604 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3605 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3606 JniValueType result;
3607 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3608 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3609 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003610 }
3611
3612 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003613 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3614 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3615 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3616 JniValueType result;
3617 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3618 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3619 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003620 }
3621
3622 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003623 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3624 JniValueType args[1] = {{.v = vm}};
3625 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3626 JniValueType result;
3627 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3628 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3629 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003630 }
3631
Ian Rogers68d8b422014-07-17 11:09:10 -07003632 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3633 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3634 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3635 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3636 JniValueType result;
3637 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3638 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3639 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003640 }
3641
3642 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003643 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3644 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003645 }
3646};
3647
3648const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003649 nullptr, // reserved0
3650 nullptr, // reserved1
3651 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003652 CheckJII::DestroyJavaVM,
3653 CheckJII::AttachCurrentThread,
3654 CheckJII::DetachCurrentThread,
3655 CheckJII::GetEnv,
3656 CheckJII::AttachCurrentThreadAsDaemon
3657};
3658
3659const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3660 return &gCheckInvokeInterface;
3661}
3662
3663} // namespace art