blob: 99277a06296111458961b81bb3b231460dbc73ba [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);
231 if (!o->InstanceOf(m->GetDeclaringClass())) {
232 AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
233 return false;
234 }
235 }
236 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700237 }
238
239 /*
240 * Verify that this static field ID is valid for this class.
241 *
242 * Assumes "java_class" has already been validated.
243 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700244 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700245 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700246 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
247 mirror::ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800248 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700249 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700250 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700251 if (f->GetDeclaringClass() != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700252 AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
253 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700254 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700255 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700256 }
257
258 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700259 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700260 *
261 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700262 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700263 * allow bad code in the system though.
264 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700265 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700266 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700267 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700268 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700269 mirror::ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800270 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700271 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700272 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700273 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700274 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700275 AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
276 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700277 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700278 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700279 }
280
281 /*
282 * Verify that "mid" is appropriate for "jobj".
283 *
284 * Make sure the object is an instance of the method's declaring class.
285 * (Note the mid might point to a declaration in an interface; this
286 * will be handled automatically by the instanceof check.)
287 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700288 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700289 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700290 mirror::ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800291 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700292 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700293 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700294 mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
Elliott Hughesa2501992011-08-26 19:39:54 -0700295 if (!o->InstanceOf(m->GetDeclaringClass())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700296 AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
297 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700298 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700299 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700300 }
301
302 /**
303 * The format string is a sequence of the following characters,
304 * and must be followed by arguments of the corresponding types
305 * in the same order.
306 *
307 * Java primitive types:
308 * B - jbyte
309 * C - jchar
310 * D - jdouble
311 * F - jfloat
312 * I - jint
313 * J - jlong
314 * S - jshort
315 * Z - jboolean (shown as true and false)
316 * V - void
317 *
318 * Java reference types:
319 * L - jobject
320 * a - jarray
321 * c - jclass
322 * s - jstring
323 *
324 * JNI types:
325 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
326 * f - jfieldID
327 * m - jmethodID
328 * p - void*
329 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700330 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700331 * z - jsize (for lengths; use i if negative values are okay)
332 * v - JavaVM*
333 * E - JNIEnv*
334 * . - no argument; just print "..." (used for varargs JNI calls)
335 *
336 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
337 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700338 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
339 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800340 mirror::ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700341 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700342 // We need to guard some of the invocation interface's calls: a bad caller might
343 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700344 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800345 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
346 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700347 }
348 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700349
Ian Rogersef7d42f2014-01-06 12:55:46 -0800350 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700351 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700352 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700353 for (size_t i = 0; fmt[i] != '\0'; ++i) {
354 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
355 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700356 StringAppendF(&msg, ", ");
357 }
358 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700359
Elliott Hughes485cac42011-12-09 17:49:35 -0800360 if ((flags_ & kFlag_ForceTrace) != 0) {
361 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
362 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700363 if (has_method_) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700364 std::string methodName(PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700365 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
366 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700367 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700368 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
369 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700370 }
371 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700372 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700373 }
374 }
375
376 // We always do the thorough checks on entry, and never on exit...
377 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700378 for (size_t i = 0; fmt[i] != '\0'; ++i) {
379 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
380 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700381 }
382 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700383 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700384 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700385 }
386
Ian Rogers68d8b422014-07-17 11:09:10 -0700387 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
388 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
389 if (!should_trace && vm->IsTracingEnabled()) {
390 // We need to guard some of the invocation interface's calls: a bad caller might
391 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
392 Thread* self = Thread::Current();
393 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
394 ScopedObjectAccess soa(self);
395 mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
396 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
397 }
398 }
399 if (should_trace) {
400 std::string msg;
401 for (size_t i = 0; fmt[i] != '\0'; ++i) {
402 TraceNonHeapValue(fmt[i], args[i], &msg);
403 if (fmt[i + 1] != '\0') {
404 StringAppendF(&msg, ", ");
405 }
406 }
407
408 if ((flags_ & kFlag_ForceTrace) != 0) {
409 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
410 } else if (entry) {
411 if (has_method_) {
412 Thread* self = Thread::Current();
413 ScopedObjectAccess soa(self);
414 mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
415 std::string methodName(PrettyMethod(traceMethod, false));
416 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
417 indent_ = methodName.size() + 1;
418 } else {
419 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
420 indent_ = 0;
421 }
422 } else {
423 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
424 }
425 }
426
427 // We always do the thorough checks on entry, and never on exit...
428 if (entry) {
429 for (size_t i = 0; fmt[i] != '\0'; ++i) {
430 if (!CheckNonHeapValue(fmt[i], args[i])) {
431 return false;
432 }
433 }
434 }
435 return true;
436 }
437
438 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
439 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
440 mirror::Object* method = soa.Decode<mirror::Object*>(jmethod);
441 if (method == nullptr) {
442 AbortF("expected non-null method");
443 return false;
444 }
445 mirror::Class* c = method->GetClass();
446 if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method) != c &&
447 soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
448 AbortF("expected java.lang.reflect.Method or "
449 "java.lang.reflect.Constructor but got object of type %s: %p",
450 PrettyTypeOf(method).c_str(), jmethod);
451 return false;
452 }
453 return true;
454 }
455
456 bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
457 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
458 mirror::ArtMethod* method = soa.DecodeMethod(mid);
459 if (method == nullptr) {
460 AbortF("expected non-null constructor");
461 return false;
462 }
463 if (!method->IsConstructor() || method->IsStatic()) {
464 AbortF("expected a constructor but %s: %p", PrettyTypeOf(method).c_str(), mid);
465 return false;
466 }
467 return true;
468 }
469
470 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
471 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
472 mirror::Object* field = soa.Decode<mirror::Object*>(jfield);
473 if (field == nullptr) {
474 AbortF("expected non-null java.lang.reflect.Field");
475 return false;
476 }
477 mirror::Class* c = field->GetClass();
478 if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Field) != c) {
479 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
480 PrettyTypeOf(field).c_str(), jfield);
481 return false;
482 }
483 return true;
484 }
485
486 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
487 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
488 mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
489 if (!obj->GetClass()->IsThrowableClass()) {
490 AbortF("expected java.lang.Throwable but got object of type "
491 "%s: %p", PrettyTypeOf(obj).c_str(), obj);
492 return false;
493 }
494 return true;
495 }
496
497 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
498 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
499 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
500 if (!c->IsThrowableClass()) {
501 AbortF("expected java.lang.Throwable class but got object of "
502 "type %s: %p", PrettyDescriptor(c).c_str(), c);
503 return false;
504 }
505 return true;
506 }
507
508 bool CheckReferenceKind(IndirectRefKind expected_kind, JavaVMExt* vm, Thread* self, jobject obj) {
509 IndirectRefKind found_kind;
510 if (expected_kind == kLocal) {
511 found_kind = GetIndirectRefKind(obj);
512 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
513 found_kind = kLocal;
514 }
515 } else {
516 found_kind = GetIndirectRefKind(obj);
517 }
518 if (obj != nullptr && found_kind != expected_kind) {
519 AbortF("expected reference of kind %s but found %s: %p",
520 ToStr<IndirectRefKind>(expected_kind).c_str(),
521 ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(),
522 obj);
523 return false;
524 }
525 return true;
526 }
527
528 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
529 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
530 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
531 if (!c->IsInstantiableNonArray()) {
532 AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c);
533 return false;
534 }
535 return true;
536 }
537
538 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
539 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
540 if (!CheckArray(soa, array)) {
541 return false;
542 }
543 mirror::Array* a = soa.Decode<mirror::Array*>(array);
544 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
545 AbortF("incompatible array type %s expected %s[]: %p",
546 PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array);
547 return false;
548 }
549 return true;
550 }
551
552 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
553 Primitive::Type type)
554 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
555 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
556 return false;
557 }
558 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
559 return false;
560 }
561 mirror::ArtField* field = soa.DecodeField(fid);
562 DCHECK(field != nullptr); // Already checked by Check.
563 if (is_static != field->IsStatic()) {
564 AbortF("attempt to access %s field %s: %p",
565 field->IsStatic() ? "static" : "non-static", PrettyField(field).c_str(), fid);
566 return false;
567 }
568 if (type != field->GetTypeAsPrimitiveType()) {
569 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
570 PrettyField(field).c_str(), PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
571 PrettyDescriptor(type).c_str(), fid);
572 return false;
573 }
574 if (is_static) {
575 mirror::Object* o = soa.Decode<mirror::Object*>(obj);
576 if (o == nullptr || !o->IsClass()) {
577 AbortF("attempt to access static field %s with a class argument of type %s: %p",
578 PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
579 return false;
580 }
581 mirror::Class* c = o->AsClass();
582 if (field->GetDeclaringClass() != c) {
583 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
584 PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid);
585 return false;
586 }
587 } else {
588 mirror::Object* o = soa.Decode<mirror::Object*>(obj);
589 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
590 AbortF("attempt to access field %s from an object argument of type %s: %p",
591 PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
592 return false;
593 }
594 }
595 return true;
596 }
597
598 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800599 enum InstanceKind {
600 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700601 kDirectByteBuffer,
602 kObject,
603 kString,
604 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800605 };
606
607 /*
608 * Verify that "jobj" is a valid non-NULL object reference, and points to
609 * an instance of expectedClass.
610 *
611 * Because we're looking at an object on the GC heap, we have to switch
612 * to "running" mode before doing the checks.
613 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700614 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700615 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800616 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800617 switch (kind) {
618 case kClass:
619 what = "jclass";
620 break;
621 case kDirectByteBuffer:
622 what = "direct ByteBuffer";
623 break;
624 case kObject:
625 what = "jobject";
626 break;
627 case kString:
628 what = "jstring";
629 break;
630 case kThrowable:
631 what = "jthrowable";
632 break;
633 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700634 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800635 }
636
Ian Rogersef7d42f2014-01-06 12:55:46 -0800637 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700638 if (null_ok) {
639 return true;
640 } else {
641 AbortF("%s received NULL %s", function_name_, what);
642 return false;
643 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800644 }
645
Ian Rogers68d8b422014-07-17 11:09:10 -0700646 mirror::Object* obj = soa.Decode<mirror::Object*>(java_object);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700647 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700648 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700649 AbortF("%s is an invalid %s: %p (%p)",
650 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
651 java_object, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800652 return false;
653 }
654
655 bool okay = true;
656 switch (kind) {
657 case kClass:
658 okay = obj->IsClass();
659 break;
660 case kDirectByteBuffer:
661 UNIMPLEMENTED(FATAL);
662 break;
663 case kString:
664 okay = obj->GetClass()->IsStringClass();
665 break;
666 case kThrowable:
667 okay = obj->GetClass()->IsThrowableClass();
668 break;
669 case kObject:
670 break;
671 }
672 if (!okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700673 AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800674 return false;
675 }
676
677 return true;
678 }
679
Ian Rogers68d8b422014-07-17 11:09:10 -0700680 /*
681 * Verify that the "mode" argument passed to a primitive array Release
682 * function is one of the valid values.
683 */
684 bool CheckReleaseMode(jint mode) {
685 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
686 AbortF("unknown value for release mode: %d", mode);
687 return false;
688 }
689 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700690 }
691
Ian Rogers68d8b422014-07-17 11:09:10 -0700692 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
693 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
694 switch (fmt) {
695 case 'a': // jarray
696 return CheckArray(soa, arg.a);
697 case 'c': // jclass
698 return CheckInstance(soa, kClass, arg.c, false);
699 case 'f': // jfieldID
700 return CheckFieldID(soa, arg.f) != nullptr;
701 case 'm': // jmethodID
702 return CheckMethodID(soa, arg.m) != nullptr;
703 case 'r': // release int
704 return CheckReleaseMode(arg.r);
705 case 's': // jstring
706 return CheckInstance(soa, kString, arg.s, false);
707 case 't': // jthrowable
708 return CheckInstance(soa, kThrowable, arg.t, false);
709 case 'E': // JNIEnv*
710 return CheckThread(arg.E);
711 case 'L': // jobject
712 return CheckInstance(soa, kObject, arg.L, true);
713 default:
714 return CheckNonHeapValue(fmt, arg);
715 }
716 }
717
718 bool CheckNonHeapValue(char fmt, JniValueType arg) {
719 switch (fmt) {
720 case '.': // ...
721 case 'p': // TODO: pointer - null or readable?
722 case 'v': // JavaVM*
723 case 'B': // jbyte
724 case 'C': // jchar
725 case 'D': // jdouble
726 case 'F': // jfloat
727 case 'I': // jint
728 case 'J': // jlong
729 case 'S': // jshort
730 break; // Ignored.
731 case 'b': // jboolean, why two? Fall-through.
732 case 'Z':
733 return CheckBoolean(arg.Z);
734 case 'u': // utf8
735 if ((flags_ & kFlag_Release) != 0) {
736 return CheckNonNull(arg.u);
737 } else {
738 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
739 return CheckUtfString(arg.u, nullable);
740 }
741 case 'w': // jobjectRefType
742 switch (arg.w) {
743 case JNIInvalidRefType:
744 case JNILocalRefType:
745 case JNIGlobalRefType:
746 case JNIWeakGlobalRefType:
747 break;
748 default:
749 AbortF("Unknown reference type");
750 return false;
751 }
752 break;
753 case 'z': // jsize
754 return CheckLengthPositive(arg.z);
755 default:
756 AbortF("unknown format specifier: '%c'", fmt);
757 return false;
758 }
759 return true;
760 }
761
762 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
763 std::string* msg)
764 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
765 switch (fmt) {
766 case 'L': // jobject fall-through.
767 case 'a': // jarray fall-through.
768 case 's': // jstring fall-through.
769 case 't': // jthrowable fall-through.
770 if (arg.L == nullptr) {
771 *msg += "NULL";
772 } else {
773 StringAppendF(msg, "%p", arg.L);
774 }
775 break;
776 case 'c': { // jclass
777 jclass jc = arg.c;
778 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
779 if (c == nullptr) {
780 *msg += "NULL";
781 } else if (c == kInvalidIndirectRefObject ||
782 !Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
783 StringAppendF(msg, "INVALID POINTER:%p", jc);
784 } else if (!c->IsClass()) {
785 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
786 } else {
787 *msg += PrettyClass(c);
788 if (!entry) {
789 StringAppendF(msg, " (%p)", jc);
790 }
791 }
792 break;
793 }
794 case 'f': { // jfieldID
795 jfieldID fid = arg.f;
796 mirror::ArtField* f = soa.DecodeField(fid);
797 *msg += PrettyField(f);
798 if (!entry) {
799 StringAppendF(msg, " (%p)", fid);
800 }
801 break;
802 }
803 case 'm': { // jmethodID
804 jmethodID mid = arg.m;
805 mirror::ArtMethod* m = soa.DecodeMethod(mid);
806 *msg += PrettyMethod(m);
807 if (!entry) {
808 StringAppendF(msg, " (%p)", mid);
809 }
810 break;
811 }
812 default:
813 TraceNonHeapValue(fmt, arg, msg);
814 break;
815 }
816 }
817
818 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
819 switch (fmt) {
820 case 'B': // jbyte
821 if (arg.B >= 0 && arg.B < 10) {
822 StringAppendF(msg, "%d", arg.B);
823 } else {
824 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
825 }
826 break;
827 case 'C': // jchar
828 if (arg.C < 0x7f && arg.C >= ' ') {
829 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
830 } else {
831 StringAppendF(msg, "U+%x", arg.C);
832 }
833 break;
834 case 'F': // jfloat
835 StringAppendF(msg, "%g", arg.F);
836 break;
837 case 'D': // jdouble
838 StringAppendF(msg, "%g", arg.D);
839 break;
840 case 'S': // jshort
841 StringAppendF(msg, "%d", arg.S);
842 break;
843 case 'i': // jint - fall-through.
844 case 'I': // jint
845 StringAppendF(msg, "%d", arg.I);
846 break;
847 case 'J': // jlong
848 StringAppendF(msg, "%" PRId64, arg.J);
849 break;
850 case 'Z': // jboolean
851 case 'b': // jboolean (JNI-style)
852 *msg += arg.b == JNI_TRUE ? "true" : "false";
853 break;
854 case 'V': // void
855 DCHECK(arg.V == nullptr);
856 *msg += "void";
857 break;
858 case 'v': // JavaVM*
859 StringAppendF(msg, "(JavaVM*)%p", arg.v);
860 break;
861 case 'E':
862 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
863 break;
864 case 'z': // non-negative jsize
865 // You might expect jsize to be size_t, but it's not; it's the same as jint.
866 // We only treat this specially so we can do the non-negative check.
867 // TODO: maybe this wasn't worth it?
868 StringAppendF(msg, "%d", arg.z);
869 break;
870 case 'p': // void* ("pointer")
871 if (arg.p == nullptr) {
872 *msg += "NULL";
873 } else {
874 StringAppendF(msg, "(void*) %p", arg.p);
875 }
876 break;
877 case 'r': { // jint (release mode)
878 jint releaseMode = arg.r;
879 if (releaseMode == 0) {
880 *msg += "0";
881 } else if (releaseMode == JNI_ABORT) {
882 *msg += "JNI_ABORT";
883 } else if (releaseMode == JNI_COMMIT) {
884 *msg += "JNI_COMMIT";
885 } else {
886 StringAppendF(msg, "invalid release mode %d", releaseMode);
887 }
888 break;
889 }
890 case 'u': // const char* (Modified UTF-8)
891 if (arg.u == nullptr) {
892 *msg += "NULL";
893 } else {
894 StringAppendF(msg, "\"%s\"", arg.u);
895 }
896 break;
897 case 'w': // jobjectRefType
898 switch (arg.w) {
899 case JNIInvalidRefType:
900 *msg += "invalid reference type";
901 break;
902 case JNILocalRefType:
903 *msg += "local ref type";
904 break;
905 case JNIGlobalRefType:
906 *msg += "global ref type";
907 break;
908 case JNIWeakGlobalRefType:
909 *msg += "weak global ref type";
910 break;
911 default:
912 *msg += "unknown ref type";
913 break;
914 }
915 break;
916 case '.':
917 *msg += "...";
918 break;
919 default:
920 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
921 }
922 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700923 /*
924 * Verify that "array" is non-NULL and points to an Array object.
925 *
926 * Since we're dealing with objects, switch to "running" mode.
927 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700928 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
929 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
930 if (UNLIKELY(java_array == nullptr)) {
931 AbortF("jarray was NULL");
932 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700933 }
934
Ian Rogers68d8b422014-07-17 11:09:10 -0700935 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
936 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700937 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700938 AbortF("jarray is an invalid %s: %p (%p)",
939 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
940 java_array, a);
941 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700942 } else if (!a->IsArrayInstance()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700943 AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
944 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700945 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700946 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700947 }
948
Ian Rogers68d8b422014-07-17 11:09:10 -0700949 bool CheckBoolean(jboolean z) {
950 if (z != JNI_TRUE && z != JNI_FALSE) {
951 AbortF("unexpected jboolean value: %d", z);
952 return false;
953 }
954 return true;
955 }
956
957 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700958 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700959 AbortF("negative jsize: %d", length);
960 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700961 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700962 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700963 }
964
Ian Rogers68d8b422014-07-17 11:09:10 -0700965 mirror::ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
966 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800967 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700968 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -0800969 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700970 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700971 mirror::ArtField* f = soa.DecodeField(fid);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700972 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700973 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700974 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800975 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700976 }
977 return f;
978 }
979
Ian Rogers68d8b422014-07-17 11:09:10 -0700980 mirror::ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
981 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800982 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700983 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -0800984 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700985 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700986 mirror::ArtMethod* m = soa.DecodeMethod(mid);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700987 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
Mathieu Chartier4c13a3f2014-07-14 14:57:16 -0700988 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700989 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800990 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700991 }
992 return m;
993 }
994
Ian Rogers68d8b422014-07-17 11:09:10 -0700995 bool CheckThread(JNIEnv* env) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700996 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800997 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700998 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
999 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001000 }
1001
1002 // Get the *correct* JNIEnv by going through our TLS pointer.
1003 JNIEnvExt* threadEnv = self->GetJniEnv();
1004
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001005 // Verify that the current thread is (a) attached and (b) associated with
1006 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001007 if (env != threadEnv) {
1008 AbortF("thread %s using JNIEnv* from thread %s",
1009 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str());
1010 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001011 }
1012
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001013 // Verify that, if this thread previously made a critical "get" call, we
1014 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001015 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001016 case kFlag_CritOkay: // okay to call this method
1017 break;
1018 case kFlag_CritBad: // not okay to call
1019 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001020 AbortF("thread %s using JNI after critical get",
1021 ToStr<Thread>(*self).c_str());
1022 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001023 }
1024 break;
1025 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001026 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001027 threadEnv->critical++;
1028 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001029 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001030 threadEnv->critical--;
1031 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001032 AbortF("thread %s called too many critical releases",
1033 ToStr<Thread>(*self).c_str());
1034 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001035 }
1036 break;
1037 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001038 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001039 }
1040
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001041 // Verify that, if an exception has been raised, the native code doesn't
1042 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001043 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001044 ThrowLocation throw_location;
1045 mirror::Throwable* exception = self->GetException(&throw_location);
1046 std::string type(PrettyTypeOf(exception));
Ian Rogers68d8b422014-07-17 11:09:10 -07001047 AbortF("JNI %s called with pending exception '%s' thrown in %s",
1048 function_name_, type.c_str(), throw_location.Dump().c_str());
1049 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001050 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001051 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001052 }
1053
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001054 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001055 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001056 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001057 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001058 AbortF("non-nullable const char* was NULL");
1059 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001060 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001061 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001062 }
1063
Ian Rogersef7d42f2014-01-06 12:55:46 -08001064 const char* errorKind = nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001065 uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001066 if (errorKind != nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001067 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1068 " string: '%s'", errorKind, utf8, bytes);
1069 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001070 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001071 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001072 }
1073
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001074 static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001075 while (*bytes != '\0') {
1076 uint8_t utf8 = *(bytes++);
1077 // Switch on the high four bits.
1078 switch (utf8 >> 4) {
1079 case 0x00:
1080 case 0x01:
1081 case 0x02:
1082 case 0x03:
1083 case 0x04:
1084 case 0x05:
1085 case 0x06:
1086 case 0x07:
1087 // Bit pattern 0xxx. No need for any extra bytes.
1088 break;
1089 case 0x08:
1090 case 0x09:
1091 case 0x0a:
1092 case 0x0b:
1093 case 0x0f:
1094 /*
1095 * Bit pattern 10xx or 1111, which are illegal start bytes.
1096 * Note: 1111 is valid for normal UTF-8, but not the
Elliott Hughes78090d12011-10-07 14:31:47 -07001097 * Modified UTF-8 used here.
Elliott Hughesa2501992011-08-26 19:39:54 -07001098 */
1099 *errorKind = "start";
1100 return utf8;
1101 case 0x0e:
1102 // Bit pattern 1110, so there are two additional bytes.
1103 utf8 = *(bytes++);
1104 if ((utf8 & 0xc0) != 0x80) {
1105 *errorKind = "continuation";
1106 return utf8;
1107 }
1108 // Fall through to take care of the final byte.
1109 case 0x0c:
1110 case 0x0d:
1111 // Bit pattern 110x, so there is one additional byte.
1112 utf8 = *(bytes++);
1113 if ((utf8 & 0xc0) != 0x80) {
1114 *errorKind = "continuation";
1115 return utf8;
1116 }
1117 break;
1118 }
1119 }
1120 return 0;
1121 }
1122
Ian Rogers68d8b422014-07-17 11:09:10 -07001123 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1124 va_list args;
1125 va_start(args, fmt);
1126 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1127 va_end(args);
1128 }
1129
1130 // The name of the JNI function being checked.
1131 const char* const function_name_;
1132
1133 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001134 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001135
Ian Rogers68d8b422014-07-17 11:09:10 -07001136 const bool has_method_;
1137
Elliott Hughesa2501992011-08-26 19:39:54 -07001138 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1139};
1140
Elliott Hughesa2501992011-08-26 19:39:54 -07001141/*
1142 * ===========================================================================
1143 * Guarded arrays
1144 * ===========================================================================
1145 */
1146
Elliott Hughesa2501992011-08-26 19:39:54 -07001147/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001148class GuardedCopy {
1149 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001150 /*
1151 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1152 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001153 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001154 static void* Create(const void* original_buf, size_t len, bool mod_okay) {
1155 const size_t new_len = LengthIncludingRedZones(len);
1156 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001157
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001158 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001159 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001160 if (!mod_okay) {
1161 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001162 }
1163
Ian Rogers68d8b422014-07-17 11:09:10 -07001164 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001165
Ian Rogers68d8b422014-07-17 11:09:10 -07001166 // Fill begin region with canary pattern.
1167 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1168 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1169 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1170 if (kCanary[j] == '\0') {
1171 j = 0;
1172 }
1173 }
1174
1175 // Copy the data in; note "len" could be zero.
1176 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1177
1178 // Fill end region with canary pattern.
1179 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1180 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1181 if (kCanary[j] == '\0') {
1182 j = 0;
1183 }
1184 }
1185
1186 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001187 }
1188
1189 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001190 * Create a guarded copy of a primitive array. Modifications to the copied
1191 * data are allowed. Returns a pointer to the copied data.
1192 */
1193 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy) {
1194 ScopedObjectAccess soa(env);
1195
1196 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1197 size_t component_size = a->GetClass()->GetComponentSize();
1198 size_t byte_count = a->GetLength() * component_size;
1199 void* result = Create(a->GetRawData(component_size, 0), byte_count, true);
1200 if (is_copy != nullptr) {
1201 *is_copy = JNI_TRUE;
1202 }
1203 return result;
1204 }
1205
1206 /*
1207 * Perform the array "release" operation, which may or may not copy data
1208 * back into the managed heap, and may or may not release the underlying storage.
1209 */
1210 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, jarray java_array,
1211 void* embedded_buf, int mode) {
1212 ScopedObjectAccess soa(env);
1213 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1214
1215 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1216 return nullptr;
1217 }
1218 if (mode != JNI_ABORT) {
1219 size_t len = FromEmbedded(embedded_buf)->original_length_;
1220 memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), embedded_buf, len);
1221 }
1222 if (mode != JNI_COMMIT) {
1223 return Destroy(embedded_buf);
1224 }
1225 return embedded_buf;
1226 }
1227
1228
1229 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001230 * Free up the guard buffer, scrub it, and return the original pointer.
1231 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001232 static void* Destroy(void* embedded_buf) {
1233 GuardedCopy* copy = FromEmbedded(embedded_buf);
1234 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1235 size_t len = LengthIncludingRedZones(copy->original_length_);
1236 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001237 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001238 }
1239
1240 /*
1241 * Verify the guard area and, if "modOkay" is false, that the data itself
1242 * has not been altered.
1243 *
1244 * The caller has already checked that "dataBuf" is non-NULL.
1245 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001246 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1247 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1248 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001249 }
1250
1251 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07001252 GuardedCopy(const void* original_buf, size_t len, uLong adler) :
1253 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1254 }
1255
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001256 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001257 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001258 if (result == MAP_FAILED) {
1259 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1260 }
1261 return reinterpret_cast<uint8_t*>(result);
1262 }
1263
Ian Rogers68d8b422014-07-17 11:09:10 -07001264 static void DebugFree(void* buf, size_t len) {
1265 if (munmap(buf, len) != 0) {
1266 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001267 }
1268 }
1269
Ian Rogers68d8b422014-07-17 11:09:10 -07001270 static size_t LengthIncludingRedZones(size_t len) {
1271 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001272 }
1273
Ian Rogers68d8b422014-07-17 11:09:10 -07001274 // Get the GuardedCopy from the interior pointer.
1275 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1276 return reinterpret_cast<GuardedCopy*>(
1277 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001278 }
1279
Ian Rogers68d8b422014-07-17 11:09:10 -07001280 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1281 return reinterpret_cast<const GuardedCopy*>(
1282 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001283 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001284
1285 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1286 va_list args;
1287 va_start(args, fmt);
1288 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1289 va_end(args);
1290 }
1291
1292 bool CheckHeader(const char* function_name, bool mod_okay) const {
1293 static const uint32_t kMagicCmp = kGuardMagic;
1294
1295 // Before we do anything with "pExtra", check the magic number. We
1296 // do the check with memcmp rather than "==" in case the pointer is
1297 // unaligned. If it points to completely bogus memory we're going
1298 // to crash, but there's no easy way around that.
1299 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1300 uint8_t buf[4];
1301 memcpy(buf, &magic_, 4);
1302 AbortF(function_name,
1303 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1304 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1305 return false;
1306 }
1307
1308 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1309 // told the client that we made a copy, there's no reason they can't alter the buffer.
1310 if (!mod_okay) {
1311 uLong computed_adler =
1312 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1313 if (computed_adler != adler_) {
1314 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1315 computed_adler, adler_, this);
1316 return false;
1317 }
1318 }
1319 return true;
1320 }
1321
1322 bool CheckRedZones(const char* function_name) const {
1323 // Check the begin red zone.
1324 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1325 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1326 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1327 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1328 return false;
1329 }
1330 if (kCanary[j] == '\0') {
1331 j = 0;
1332 }
1333 }
1334
1335 // Check end region.
1336 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1337 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1338 size_t offset_from_buffer_start =
1339 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1340 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1341 offset_from_buffer_start);
1342 return false;
1343 }
1344 if (kCanary[j] == '\0') {
1345 j = 0;
1346 }
1347 }
1348 return true;
1349 }
1350
1351 // Location that canary value will be written before the guarded region.
1352 const char* StartRedZone() const {
1353 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1354 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1355 }
1356
1357 // Return the interior embedded buffer.
1358 const uint8_t* BufferWithinRedZones() const {
1359 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1360 return embedded_buf;
1361 }
1362
1363 // Location that canary value will be written after the guarded region.
1364 const char* EndRedZone() const {
1365 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1366 size_t buf_len = LengthIncludingRedZones(original_length_);
1367 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1368 }
1369
1370 static constexpr size_t kRedZoneSize = 512;
1371 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1372
1373 // Value written before and after the guarded array.
1374 static const char* const kCanary;
1375
1376 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1377
1378 const uint32_t magic_;
1379 const uLong adler_;
1380 const void* const original_ptr_;
1381 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001382};
Ian Rogers68d8b422014-07-17 11:09:10 -07001383const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001384
1385/*
1386 * ===========================================================================
1387 * JNI functions
1388 * ===========================================================================
1389 */
1390
1391class CheckJNI {
1392 public:
1393 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001394 ScopedObjectAccess soa(env);
1395 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1396 JniValueType args[1] = {{.E = env }};
1397 if (sc.Check(soa, true, "E", args)) {
1398 JniValueType result;
1399 result.I = baseEnv(env)->GetVersion(env);
1400 if (sc.Check(soa, false, "I", &result)) {
1401 return result.I;
1402 }
1403 }
1404 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001405 }
1406
Ian Rogers68d8b422014-07-17 11:09:10 -07001407 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1408 ScopedObjectAccess soa(env);
1409 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1410 JniValueType args[2] = {{.E = env }, {.p = vm}};
1411 if (sc.Check(soa, true, "Ep", args)) {
1412 JniValueType result;
1413 result.i = baseEnv(env)->GetJavaVM(env, vm);
1414 if (sc.Check(soa, false, "i", &result)) {
1415 return result.i;
1416 }
1417 }
1418 return JNI_ERR;
1419 }
1420
1421 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1422 ScopedObjectAccess soa(env);
1423 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1424 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1425 if (sc.Check(soa, true, "EcpI", args)) {
1426 JniValueType result;
1427 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1428 if (sc.Check(soa, false, "i", &result)) {
1429 return result.i;
1430 }
1431 }
1432 return JNI_ERR;
1433 }
1434
1435 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1436 ScopedObjectAccess soa(env);
1437 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1438 JniValueType args[2] = {{.E = env }, {.c = c}};
1439 if (sc.Check(soa, true, "Ec", args)) {
1440 JniValueType result;
1441 result.i = baseEnv(env)->UnregisterNatives(env, c);
1442 if (sc.Check(soa, false, "i", &result)) {
1443 return result.i;
1444 }
1445 }
1446 return JNI_ERR;
1447 }
1448
1449 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1450 // Note: we use "Ep" rather than "EL" because this is the one JNI function that it's okay to
1451 // pass an invalid reference to.
1452 ScopedObjectAccess soa(env);
1453 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1454 JniValueType args[2] = {{.E = env }, {.p = obj}};
1455 if (sc.Check(soa, true, "Ep", args)) {
1456 JniValueType result;
1457 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1458 if (sc.Check(soa, false, "w", &result)) {
1459 return result.w;
1460 }
1461 }
1462 return JNIInvalidRefType;
1463 }
1464
1465 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1466 jsize bufLen) {
1467 ScopedObjectAccess soa(env);
1468 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1469 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1470 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1471 JniValueType result;
1472 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1473 if (sc.Check(soa, false, "c", &result)) {
1474 return result.c;
1475 }
1476 }
1477 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001478 }
1479
1480 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001481 ScopedObjectAccess soa(env);
1482 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1483 JniValueType args[2] = {{.E = env}, {.u = name}};
1484 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1485 JniValueType result;
1486 result.c = baseEnv(env)->FindClass(env, name);
1487 if (sc.Check(soa, false, "c", &result)) {
1488 return result.c;
1489 }
1490 }
1491 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001492 }
1493
Elliott Hughese84278b2012-03-22 10:06:53 -07001494 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001495 ScopedObjectAccess soa(env);
1496 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1497 JniValueType args[2] = {{.E = env}, {.c = c}};
1498 if (sc.Check(soa, true, "Ec", args)) {
1499 JniValueType result;
1500 result.c = baseEnv(env)->GetSuperclass(env, c);
1501 if (sc.Check(soa, false, "c", &result)) {
1502 return result.c;
1503 }
1504 }
1505 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001506 }
1507
Elliott Hughese84278b2012-03-22 10:06:53 -07001508 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001509 ScopedObjectAccess soa(env);
1510 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1511 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1512 if (sc.Check(soa, true, "Ecc", args)) {
1513 JniValueType result;
1514 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1515 if (sc.Check(soa, false, "b", &result)) {
1516 return result.b;
1517 }
1518 }
1519 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001520 }
1521
1522 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001523 ScopedObjectAccess soa(env);
1524 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1525 JniValueType args[2] = {{.E = env}, {.L = method}};
1526 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1527 JniValueType result;
1528 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1529 if (sc.Check(soa, false, "m", &result)) {
1530 return result.m;
1531 }
1532 }
1533 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001534 }
1535
1536 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001537 ScopedObjectAccess soa(env);
1538 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1539 JniValueType args[2] = {{.E = env}, {.L = field}};
1540 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1541 JniValueType result;
1542 result.f = baseEnv(env)->FromReflectedField(env, field);
1543 if (sc.Check(soa, false, "f", &result)) {
1544 return result.f;
1545 }
1546 }
1547 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001548 }
1549
1550 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001551 ScopedObjectAccess soa(env);
1552 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1553 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1554 if (sc.Check(soa, true, "Ecmb", args)) {
1555 JniValueType result;
1556 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1557 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1558 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1559 return result.L;
1560 }
1561 }
1562 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001563 }
1564
1565 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001566 ScopedObjectAccess soa(env);
1567 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1568 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1569 if (sc.Check(soa, true, "Ecfb", args)) {
1570 JniValueType result;
1571 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1572 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1573 DCHECK(sc.CheckReflectedField(soa, result.L));
1574 return result.L;
1575 }
1576 }
1577 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001578 }
1579
1580 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001581 ScopedObjectAccess soa(env);
1582 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1583 JniValueType args[2] = {{.E = env}, {.t = obj}};
1584 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1585 JniValueType result;
1586 result.i = baseEnv(env)->Throw(env, obj);
1587 if (sc.Check(soa, false, "i", &result)) {
1588 return result.i;
1589 }
1590 }
1591 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001592 }
1593
Elliott Hughese84278b2012-03-22 10:06:53 -07001594 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001595 ScopedObjectAccess soa(env);
1596 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
1597 JniValueType args[5] = {{.E = env}, {.c = c}, {.u = message}};
1598 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1599 JniValueType result;
1600 result.i = baseEnv(env)->ThrowNew(env, c, message);
1601 if (sc.Check(soa, false, "i", &result)) {
1602 return result.i;
1603 }
1604 }
1605 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001606 }
1607
1608 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001609 ScopedObjectAccess soa(env);
1610 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1611 JniValueType args[1] = {{.E = env}};
1612 if (sc.Check(soa, true, "E", args)) {
1613 JniValueType result;
1614 result.t = baseEnv(env)->ExceptionOccurred(env);
1615 if (sc.Check(soa, false, "t", &result)) {
1616 return result.t;
1617 }
1618 }
1619 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001620 }
1621
1622 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001623 ScopedObjectAccess soa(env);
1624 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1625 JniValueType args[1] = {{.E = env}};
1626 if (sc.Check(soa, true, "E", args)) {
1627 JniValueType result;
1628 baseEnv(env)->ExceptionDescribe(env);
1629 result.V = nullptr;
1630 sc.Check(soa, false, "V", &result);
1631 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001632 }
1633
1634 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001635 ScopedObjectAccess soa(env);
1636 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1637 JniValueType args[1] = {{.E = env}};
1638 if (sc.Check(soa, true, "E", args)) {
1639 JniValueType result;
1640 baseEnv(env)->ExceptionClear(env);
1641 result.V = nullptr;
1642 sc.Check(soa, false, "V", &result);
1643 }
1644 }
1645
1646 static jboolean ExceptionCheck(JNIEnv* env) {
1647 ScopedObjectAccess soa(env);
1648 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1649 JniValueType args[1] = {{.E = env}};
1650 if (sc.Check(soa, true, "E", args)) {
1651 JniValueType result;
1652 result.b = baseEnv(env)->ExceptionCheck(env);
1653 if (sc.Check(soa, false, "b", &result)) {
1654 return result.b;
1655 }
1656 }
1657 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001658 }
1659
1660 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001661 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1662 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1663 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001664 ScopedObjectAccess soa(env);
1665 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1666 JniValueType args[2] = {{.E = env}, {.u = msg}};
1667 if (sc.Check(soa, true, "Eu", args)) {
1668 JniValueType result;
1669 baseEnv(env)->FatalError(env, msg);
1670 // Unreachable.
1671 result.V = nullptr;
1672 sc.Check(soa, false, "V", &result);
1673 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001674 }
1675
1676 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001677 ScopedObjectAccess soa(env);
1678 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1679 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1680 if (sc.Check(soa, true, "EI", args)) {
1681 JniValueType result;
1682 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1683 if (sc.Check(soa, false, "i", &result)) {
1684 return result.i;
1685 }
1686 }
1687 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001688 }
1689
1690 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001691 ScopedObjectAccess soa(env);
1692 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1693 JniValueType args[2] = {{.E = env}, {.L = res}};
1694 if (sc.Check(soa, true, "EL", args)) {
1695 JniValueType result;
1696 result.L = baseEnv(env)->PopLocalFrame(env, res);
1697 sc.Check(soa, false, "L", &result);
1698 return result.L;
1699 }
1700 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001701 }
1702
1703 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001704 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001705 }
1706
Ian Rogers68d8b422014-07-17 11:09:10 -07001707 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1708 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001709 }
1710
1711 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001712 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001713 }
1714
Ian Rogers68d8b422014-07-17 11:09:10 -07001715 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1716 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001717 }
1718
Ian Rogers68d8b422014-07-17 11:09:10 -07001719 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1720 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1721 }
1722
1723 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1724 DeleteRef(__FUNCTION__, env, obj, kLocal);
1725 }
1726
1727 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1728 ScopedObjectAccess soa(env);
1729 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1730 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1731 if (sc.Check(soa, true, "EI", args)) {
1732 JniValueType result;
1733 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1734 if (sc.Check(soa, false, "i", &result)) {
1735 return result.i;
1736 }
1737 }
1738 return JNI_ERR;
1739 }
1740
1741 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1742 ScopedObjectAccess soa(env);
1743 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1744 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1745 if (sc.Check(soa, true, "ELL", args)) {
1746 JniValueType result;
1747 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1748 if (sc.Check(soa, false, "b", &result)) {
1749 return result.b;
1750 }
1751 }
1752 return JNI_FALSE;
1753 }
1754
1755 static jobject AllocObject(JNIEnv* env, jclass c) {
1756 ScopedObjectAccess soa(env);
1757 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1758 JniValueType args[2] = {{.E = env}, {.c = c}};
1759 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1760 JniValueType result;
1761 result.L = baseEnv(env)->AllocObject(env, c);
1762 if (sc.Check(soa, false, "L", &result)) {
1763 return result.L;
1764 }
1765 }
1766 return nullptr;
1767 }
1768
1769 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1770 ScopedObjectAccess soa(env);
1771 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1772 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
1773 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
1774 sc.CheckConstructor(soa, mid)) {
1775 JniValueType result;
1776 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
1777 if (sc.Check(soa, false, "L", &result)) {
1778 return result.L;
1779 }
1780 }
1781 return nullptr;
1782 }
1783
1784 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1785 va_list args;
1786 va_start(args, mid);
1787 jobject result = NewObjectV(env, c, mid, args);
1788 va_end(args);
1789 return result;
1790 }
1791
1792 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
1793 ScopedObjectAccess soa(env);
1794 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1795 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
1796 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
1797 sc.CheckConstructor(soa, mid)) {
1798 JniValueType result;
1799 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
1800 if (sc.Check(soa, false, "L", &result)) {
1801 return result.L;
1802 }
1803 }
1804 return nullptr;
1805 }
1806
1807 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1808 ScopedObjectAccess soa(env);
1809 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1810 JniValueType args[2] = {{.E = env}, {.L = obj}};
1811 if (sc.Check(soa, true, "EL", args)) {
1812 JniValueType result;
1813 result.c = baseEnv(env)->GetObjectClass(env, obj);
1814 if (sc.Check(soa, false, "c", &result)) {
1815 return result.c;
1816 }
1817 }
1818 return nullptr;
1819 }
1820
1821 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1822 ScopedObjectAccess soa(env);
1823 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1824 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
1825 if (sc.Check(soa, true, "ELc", args)) {
1826 JniValueType result;
1827 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
1828 if (sc.Check(soa, false, "b", &result)) {
1829 return result.b;
1830 }
1831 }
1832 return JNI_FALSE;
1833 }
1834
1835 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1836 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
1837 }
1838
1839 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1840 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
1841 }
1842
1843 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1844 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
1845 }
1846
1847 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1848 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
1849 }
1850
1851#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
1852 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1853 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
1854 } \
1855 \
1856 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1857 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
1858 } \
1859 \
1860 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
1861 JniValueType value; \
1862 value.shorty = v; \
1863 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
1864 } \
1865 \
1866 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
1867 JniValueType value; \
1868 value.shorty = v; \
1869 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
1870 }
1871
1872 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
1873 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
1874 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
1875 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
1876 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
1877 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
1878 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
1879 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
1880 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
1881#undef FIELD_ACCESSORS
1882
1883 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
1884 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1885 }
1886
1887 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1888 jvalue* vargs) {
1889 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1890 }
1891
1892 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
1893 CallMethodA(__FUNCTION__, env, c, nullptr, mid, vargs, Primitive::kPrimVoid, kStatic);
1894 }
1895
1896 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
1897 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1898 }
1899
1900 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
1901 va_list vargs) {
1902 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1903 }
1904
1905 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1906 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1907 }
1908
1909 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1910 va_list vargs;
1911 va_start(vargs, mid);
1912 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
1913 va_end(vargs);
1914 }
1915
1916 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
1917 va_list vargs;
1918 va_start(vargs, mid);
1919 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
1920 va_end(vargs);
1921 }
1922
1923 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
1924 va_list vargs;
1925 va_start(vargs, mid);
1926 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
1927 va_end(vargs);
1928 }
1929
1930#define CALL(rtype, name, ptype, shorty) \
1931 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
1932 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1933 } \
1934 \
1935 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1936 jvalue* vargs) { \
1937 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1938 } \
1939 \
1940 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
1941 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1942 } \
1943 \
1944 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
1945 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1946 } \
1947 \
1948 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1949 va_list vargs) { \
1950 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1951 } \
1952 \
1953 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
1954 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1955 } \
1956 \
1957 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
1958 va_list vargs; \
1959 va_start(vargs, mid); \
1960 rtype result = \
1961 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
1962 va_end(vargs); \
1963 return result; \
1964 } \
1965 \
1966 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
1967 ...) { \
1968 va_list vargs; \
1969 va_start(vargs, mid); \
1970 rtype result = \
1971 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
1972 va_end(vargs); \
1973 return result; \
1974 } \
1975 \
1976 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
1977 va_list vargs; \
1978 va_start(vargs, mid); \
1979 rtype result = \
1980 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
1981 va_end(vargs); \
1982 return result; \
1983 }
1984
1985 CALL(jobject, Object, Primitive::kPrimNot, L)
1986 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
1987 CALL(jbyte, Byte, Primitive::kPrimByte, B)
1988 CALL(jchar, Char, Primitive::kPrimChar, C)
1989 CALL(jshort, Short, Primitive::kPrimShort, S)
1990 CALL(jint, Int, Primitive::kPrimInt, I)
1991 CALL(jlong, Long, Primitive::kPrimLong, J)
1992 CALL(jfloat, Float, Primitive::kPrimFloat, F)
1993 CALL(jdouble, Double, Primitive::kPrimDouble, D)
1994#undef CALL
1995
1996 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
1997 ScopedObjectAccess soa(env);
1998 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1999 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2000 if (sc.Check(soa, true, "Epz", args)) {
2001 JniValueType result;
2002 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2003 if (sc.Check(soa, false, "s", &result)) {
2004 return result.s;
2005 }
2006 }
2007 return nullptr;
2008 }
2009
2010 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2011 ScopedObjectAccess soa(env);
2012 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2013 JniValueType args[2] = {{.E = env}, {.u = chars}};
2014 if (sc.Check(soa, true, "Eu", args)) {
2015 JniValueType result;
2016 // TODO: stale? show pointer and truncate string.
2017 result.s = baseEnv(env)->NewStringUTF(env, chars);
2018 if (sc.Check(soa, false, "s", &result)) {
2019 return result.s;
2020 }
2021 }
2022 return nullptr;
2023 }
2024
2025 static jsize GetStringLength(JNIEnv* env, jstring string) {
2026 ScopedObjectAccess soa(env);
2027 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2028 JniValueType args[2] = {{.E = env}, {.s = string}};
2029 if (sc.Check(soa, true, "Es", args)) {
2030 JniValueType result;
2031 result.z = baseEnv(env)->GetStringLength(env, string);
2032 if (sc.Check(soa, false, "z", &result)) {
2033 return result.z;
2034 }
2035 }
2036 return JNI_ERR;
2037 }
2038
2039 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2040 ScopedObjectAccess soa(env);
2041 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2042 JniValueType args[2] = {{.E = env}, {.s = string}};
2043 if (sc.Check(soa, true, "Es", args)) {
2044 JniValueType result;
2045 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2046 if (sc.Check(soa, false, "z", &result)) {
2047 return result.z;
2048 }
2049 }
2050 return JNI_ERR;
2051 }
2052
2053 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2054 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2055 is_copy, false, false));
2056 }
2057
2058 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2059 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2060 is_copy, true, false));
2061 }
2062
2063 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2064 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2065 is_copy, false, true));
2066 }
2067
2068 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2069 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2070 }
2071
2072 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2073 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2074 }
2075
2076 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2077 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2078 }
2079
2080 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2081 ScopedObjectAccess soa(env);
2082 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2083 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2084 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2085 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2086 if (sc.Check(soa, true, "EsIIp", args)) {
2087 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2088 JniValueType result;
2089 result.V = nullptr;
2090 sc.Check(soa, false, "V", &result);
2091 }
2092 }
2093
2094 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2095 ScopedObjectAccess soa(env);
2096 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2097 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2098 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2099 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2100 if (sc.Check(soa, true, "EsIIp", args)) {
2101 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2102 JniValueType result;
2103 result.V = nullptr;
2104 sc.Check(soa, false, "V", &result);
2105 }
2106 }
2107
2108 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2109 ScopedObjectAccess soa(env);
2110 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2111 JniValueType args[2] = {{.E = env}, {.a = array}};
2112 if (sc.Check(soa, true, "Ea", args)) {
2113 JniValueType result;
2114 result.z = baseEnv(env)->GetArrayLength(env, array);
2115 if (sc.Check(soa, false, "z", &result)) {
2116 return result.z;
2117 }
2118 }
2119 return JNI_ERR;
2120 }
2121
2122 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2123 jobject initial_element) {
2124 ScopedObjectAccess soa(env);
2125 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2126 JniValueType args[4] =
2127 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2128 if (sc.Check(soa, true, "EzcL", args)) {
2129 JniValueType result;
2130 // Note: assignability tests of initial_element are done in the base implementation.
2131 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2132 if (sc.Check(soa, false, "a", &result)) {
2133 return down_cast<jobjectArray>(result.a);
2134 }
2135 }
2136 return nullptr;
2137 }
2138
2139 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2140 ScopedObjectAccess soa(env);
2141 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2142 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2143 if (sc.Check(soa, true, "Eaz", args)) {
2144 JniValueType result;
2145 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2146 if (sc.Check(soa, false, "L", &result)) {
2147 return result.L;
2148 }
2149 }
2150 return nullptr;
2151 }
2152
2153 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2154 ScopedObjectAccess soa(env);
2155 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2156 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2157 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2158 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2159 // in ArrayStoreExceptions.
2160 if (sc.Check(soa, true, "EaIL", args)) {
2161 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2162 JniValueType result;
2163 result.V = nullptr;
2164 sc.Check(soa, false, "V", &result);
2165 }
2166 }
2167
2168 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2169 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2170 Primitive::kPrimBoolean));
2171 }
2172
2173 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2174 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2175 Primitive::kPrimByte));
2176 }
2177
2178 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2179 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2180 Primitive::kPrimChar));
2181 }
2182
2183 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2184 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2185 Primitive::kPrimShort));
2186 }
2187
2188 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2189 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2190 }
2191
2192 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2193 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2194 Primitive::kPrimLong));
2195 }
2196
2197 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2198 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2199 Primitive::kPrimFloat));
2200 }
2201
2202 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2203 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2204 Primitive::kPrimDouble));
2205 }
2206
2207#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2208 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \
2209 return reinterpret_cast<ctype*>( \
2210 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2211 } \
2212 \
2213 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \
2214 jint mode) { \
2215 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2216 } \
2217 \
2218 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2219 ctype* buf) { \
2220 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2221 } \
2222 \
2223 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2224 const ctype* buf) { \
2225 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2226 }
2227
2228 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2229 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2230 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2231 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2232 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2233 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2234 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2235 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2236#undef PRIMITIVE_ARRAY_FUNCTIONS
2237
2238 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2239 ScopedObjectAccess soa(env);
2240 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2241 JniValueType args[2] = {{.E = env}, {.L = obj}};
2242 if (sc.Check(soa, true, "EL", args)) {
2243 JniValueType result;
2244 result.i = baseEnv(env)->MonitorEnter(env, obj);
2245 if (sc.Check(soa, false, "i", &result)) {
2246 return result.i;
2247 }
2248 }
2249 return JNI_ERR;
2250 }
2251
2252 static jint MonitorExit(JNIEnv* env, jobject obj) {
2253 ScopedObjectAccess soa(env);
2254 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2255 JniValueType args[2] = {{.E = env}, {.L = obj}};
2256 if (sc.Check(soa, true, "EL", args)) {
2257 JniValueType result;
2258 result.i = baseEnv(env)->MonitorExit(env, obj);
2259 if (sc.Check(soa, false, "i", &result)) {
2260 return result.i;
2261 }
2262 }
2263 return JNI_ERR;
2264 }
2265
2266 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2267 ScopedObjectAccess soa(env);
2268 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2269 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2270 if (sc.Check(soa, true, "Eap", args)) {
2271 JniValueType result;
2272 result.p = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2273 if (result.p != nullptr && soa.ForceCopy()) {
2274 result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
2275 }
2276 if (sc.Check(soa, false, "p", &result)) {
2277 return const_cast<void*>(result.p);
2278 }
2279 }
2280 return nullptr;
2281 }
2282
2283 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2284 ScopedObjectAccess soa(env);
2285 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2286 sc.CheckNonNull(carray);
2287 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2288 if (sc.Check(soa, true, "Eapr", args)) {
2289 if (soa.ForceCopy()) {
2290 GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
2291 }
2292 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2293 JniValueType result;
2294 result.V = nullptr;
2295 sc.Check(soa, false, "V", &result);
2296 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002297 }
2298
2299 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002300 ScopedObjectAccess soa(env);
2301 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2302 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2303 if (sc.Check(soa, true, "EpJ", args)) {
2304 JniValueType result;
2305 // Note: the validity of address and capacity are checked in the base implementation.
2306 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2307 if (sc.Check(soa, false, "L", &result)) {
2308 return result.L;
2309 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002310 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002311 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002312 }
2313
2314 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002315 ScopedObjectAccess soa(env);
2316 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2317 JniValueType args[2] = {{.E = env}, {.L = buf}};
2318 if (sc.Check(soa, true, "EL", args)) {
2319 JniValueType result;
2320 // Note: this is implemented in the base environment by a GetLongField which will sanity
2321 // check the type of buf in GetLongField above.
2322 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2323 if (sc.Check(soa, false, "p", &result)) {
2324 return const_cast<void*>(result.p);
2325 }
2326 }
2327 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002328 }
2329
2330 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002331 ScopedObjectAccess soa(env);
2332 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2333 JniValueType args[2] = {{.E = env}, {.L = buf}};
2334 if (sc.Check(soa, true, "EL", args)) {
2335 JniValueType result;
2336 // Note: this is implemented in the base environment by a GetIntField which will sanity
2337 // check the type of buf in GetIntField above.
2338 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2339 if (sc.Check(soa, false, "J", &result)) {
2340 return result.J;
2341 }
2342 }
2343 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002344 }
2345
2346 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002347 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2348 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2349 }
2350
2351 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002352 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2353 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002354
2355 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2356 ScopedObjectAccess soa(env);
2357 ScopedCheck sc(kFlag_Default, function_name);
2358 JniValueType args[2] = {{.E = env}, {.L = obj}};
2359 if (sc.Check(soa, true, "EL", args)) {
2360 JniValueType result;
2361 switch (kind) {
2362 case kGlobal:
2363 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2364 break;
2365 case kLocal:
2366 result.L = baseEnv(env)->NewLocalRef(env, obj);
2367 break;
2368 case kWeakGlobal:
2369 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2370 break;
2371 default:
2372 LOG(FATAL) << "Unexpected reference kind: " << kind;
2373 }
2374 if (sc.Check(soa, false, "L", &result)) {
2375 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
2376 DCHECK(sc.CheckReferenceKind(kind, soa.Vm(), soa.Self(), result.L));
2377 return result.L;
2378 }
2379 }
2380 return nullptr;
2381 }
2382
2383 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2384 ScopedObjectAccess soa(env);
2385 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2386 JniValueType args[2] = {{.E = env}, {.L = obj}};
2387 sc.Check(soa, true, "EL", args);
2388 if (sc.CheckReferenceKind(kind, soa.Vm(), soa.Self(), obj)) {
2389 JniValueType result;
2390 switch (kind) {
2391 case kGlobal:
2392 baseEnv(env)->DeleteGlobalRef(env, obj);
2393 break;
2394 case kLocal:
2395 baseEnv(env)->DeleteLocalRef(env, obj);
2396 break;
2397 case kWeakGlobal:
2398 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2399 break;
2400 default:
2401 LOG(FATAL) << "Unexpected reference kind: " << kind;
2402 }
2403 result.V = nullptr;
2404 sc.Check(soa, false, "V", &result);
2405 }
2406 }
2407
2408 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2409 const char* name, const char* sig, bool is_static) {
2410 ScopedObjectAccess soa(env);
2411 ScopedCheck sc(kFlag_Default, function_name);
2412 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2413 if (sc.Check(soa, true, "Ecuu", args)) {
2414 JniValueType result;
2415 if (is_static) {
2416 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2417 } else {
2418 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2419 }
2420 if (sc.Check(soa, false, "m", &result)) {
2421 return result.m;
2422 }
2423 }
2424 return nullptr;
2425 }
2426
2427 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2428 const char* name, const char* sig, bool is_static) {
2429 ScopedObjectAccess soa(env);
2430 ScopedCheck sc(kFlag_Default, function_name);
2431 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2432 if (sc.Check(soa, true, "Ecuu", args)) {
2433 JniValueType result;
2434 if (is_static) {
2435 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2436 } else {
2437 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2438 }
2439 if (sc.Check(soa, false, "f", &result)) {
2440 return result.f;
2441 }
2442 }
2443 return nullptr;
2444 }
2445
2446 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2447 bool is_static, Primitive::Type type) {
2448 ScopedObjectAccess soa(env);
2449 ScopedCheck sc(kFlag_Default, function_name);
2450 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2451 JniValueType result;
2452 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2453 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2454 const char* result_check = nullptr;
2455 switch (type) {
2456 case Primitive::kPrimNot:
2457 if (is_static) {
2458 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2459 } else {
2460 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2461 }
2462 result_check = "L";
2463 break;
2464 case Primitive::kPrimBoolean:
2465 if (is_static) {
2466 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2467 } else {
2468 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2469 }
2470 result_check = "Z";
2471 break;
2472 case Primitive::kPrimByte:
2473 if (is_static) {
2474 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2475 } else {
2476 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2477 }
2478 result_check = "B";
2479 break;
2480 case Primitive::kPrimChar:
2481 if (is_static) {
2482 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2483 } else {
2484 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2485 }
2486 result_check = "C";
2487 break;
2488 case Primitive::kPrimShort:
2489 if (is_static) {
2490 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2491 } else {
2492 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2493 }
2494 result_check = "S";
2495 break;
2496 case Primitive::kPrimInt:
2497 if (is_static) {
2498 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2499 } else {
2500 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2501 }
2502 result_check = "I";
2503 break;
2504 case Primitive::kPrimLong:
2505 if (is_static) {
2506 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2507 } else {
2508 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2509 }
2510 result_check = "J";
2511 break;
2512 case Primitive::kPrimFloat:
2513 if (is_static) {
2514 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2515 } else {
2516 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2517 }
2518 result_check = "F";
2519 break;
2520 case Primitive::kPrimDouble:
2521 if (is_static) {
2522 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2523 } else {
2524 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2525 }
2526 result_check = "D";
2527 break;
2528 case Primitive::kPrimVoid:
2529 LOG(FATAL) << "Unexpected type: " << type;
2530 break;
2531 }
2532 if (sc.Check(soa, false, result_check, &result)) {
2533 return result;
2534 }
2535 }
2536 result.J = 0;
2537 return result;
2538 }
2539
2540 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2541 bool is_static, Primitive::Type type, JniValueType value) {
2542 ScopedObjectAccess soa(env);
2543 ScopedCheck sc(kFlag_Default, function_name);
2544 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2545 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2546 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2547 if (sc.Check(soa, true, sig, args) &&
2548 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2549 switch (type) {
2550 case Primitive::kPrimNot:
2551 if (is_static) {
2552 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2553 } else {
2554 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2555 }
2556 break;
2557 case Primitive::kPrimBoolean:
2558 if (is_static) {
2559 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2560 } else {
2561 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2562 }
2563 break;
2564 case Primitive::kPrimByte:
2565 if (is_static) {
2566 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2567 } else {
2568 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2569 }
2570 break;
2571 case Primitive::kPrimChar:
2572 if (is_static) {
2573 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2574 } else {
2575 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2576 }
2577 break;
2578 case Primitive::kPrimShort:
2579 if (is_static) {
2580 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2581 } else {
2582 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2583 }
2584 break;
2585 case Primitive::kPrimInt:
2586 if (is_static) {
2587 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2588 } else {
2589 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2590 }
2591 break;
2592 case Primitive::kPrimLong:
2593 if (is_static) {
2594 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2595 } else {
2596 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2597 }
2598 break;
2599 case Primitive::kPrimFloat:
2600 if (is_static) {
2601 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2602 } else {
2603 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2604 }
2605 break;
2606 case Primitive::kPrimDouble:
2607 if (is_static) {
2608 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2609 } else {
2610 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2611 }
2612 break;
2613 case Primitive::kPrimVoid:
2614 LOG(FATAL) << "Unexpected type: " << type;
2615 break;
2616 }
2617 JniValueType result;
2618 result.V = nullptr;
2619 sc.Check(soa, false, "V", &result);
2620 }
2621 }
2622
2623 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
2624 jclass c, jmethodID mid, InvokeType invoke)
2625 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2626 bool checked;
2627 switch (invoke) {
2628 case kVirtual: {
2629 DCHECK(c == nullptr);
2630 JniValueType args[3] = {{.E = env}, {.L = obj}, {.m = mid}};
2631 checked = sc.Check(soa, true, "ELm.", args);
2632 break;
2633 }
2634 case kDirect: {
2635 JniValueType args[4] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}};
2636 checked = sc.Check(soa, true, "ELcm.", args);
2637 break;
2638 }
2639 case kStatic: {
2640 DCHECK(obj == nullptr);
2641 JniValueType args[3] = {{.E = env}, {.c = c}, {.m = mid}};
2642 checked = sc.Check(soa, true, "Ecm.", args);
2643 break;
2644 }
2645 default:
2646 LOG(FATAL) << "Unexpected invoke: " << invoke;
2647 checked = false;
2648 break;
2649 }
2650 return checked;
2651 }
2652
2653 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2654 jmethodID mid, jvalue* vargs, Primitive::Type type,
2655 InvokeType invoke) {
2656 ScopedObjectAccess soa(env);
2657 ScopedCheck sc(kFlag_Default, function_name);
2658 JniValueType result;
2659 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2660 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2661 const char* result_check;
2662 switch (type) {
2663 case Primitive::kPrimNot:
2664 result_check = "L";
2665 switch (invoke) {
2666 case kVirtual:
2667 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2668 break;
2669 case kDirect:
2670 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2671 break;
2672 case kStatic:
2673 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2674 break;
2675 default:
2676 break;
2677 }
2678 break;
2679 case Primitive::kPrimBoolean:
2680 result_check = "Z";
2681 switch (invoke) {
2682 case kVirtual:
2683 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2684 break;
2685 case kDirect:
2686 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2687 break;
2688 case kStatic:
2689 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2690 break;
2691 default:
2692 break;
2693 }
2694 break;
2695 case Primitive::kPrimByte:
2696 result_check = "B";
2697 switch (invoke) {
2698 case kVirtual:
2699 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2700 break;
2701 case kDirect:
2702 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2703 break;
2704 case kStatic:
2705 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2706 break;
2707 default:
2708 break;
2709 }
2710 break;
2711 case Primitive::kPrimChar:
2712 result_check = "C";
2713 switch (invoke) {
2714 case kVirtual:
2715 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2716 break;
2717 case kDirect:
2718 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2719 break;
2720 case kStatic:
2721 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2722 break;
2723 default:
2724 break;
2725 }
2726 break;
2727 case Primitive::kPrimShort:
2728 result_check = "S";
2729 switch (invoke) {
2730 case kVirtual:
2731 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2732 break;
2733 case kDirect:
2734 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2735 break;
2736 case kStatic:
2737 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2738 break;
2739 default:
2740 break;
2741 }
2742 break;
2743 case Primitive::kPrimInt:
2744 result_check = "I";
2745 switch (invoke) {
2746 case kVirtual:
2747 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2748 break;
2749 case kDirect:
2750 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2751 break;
2752 case kStatic:
2753 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2754 break;
2755 default:
2756 break;
2757 }
2758 break;
2759 case Primitive::kPrimLong:
2760 result_check = "J";
2761 switch (invoke) {
2762 case kVirtual:
2763 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
2764 break;
2765 case kDirect:
2766 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
2767 break;
2768 case kStatic:
2769 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
2770 break;
2771 default:
2772 break;
2773 }
2774 break;
2775 case Primitive::kPrimFloat:
2776 result_check = "F";
2777 switch (invoke) {
2778 case kVirtual:
2779 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
2780 break;
2781 case kDirect:
2782 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
2783 break;
2784 case kStatic:
2785 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
2786 break;
2787 default:
2788 break;
2789 }
2790 break;
2791 case Primitive::kPrimDouble:
2792 result_check = "D";
2793 switch (invoke) {
2794 case kVirtual:
2795 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
2796 break;
2797 case kDirect:
2798 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
2799 break;
2800 case kStatic:
2801 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
2802 break;
2803 default:
2804 break;
2805 }
2806 break;
2807 case Primitive::kPrimVoid:
2808 result_check = "V";
2809 result.V = nullptr;
2810 switch (invoke) {
2811 case kVirtual:
2812 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
2813 break;
2814 case kDirect:
2815 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
2816 break;
2817 case kStatic:
2818 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
2819 break;
2820 default:
2821 LOG(FATAL) << "Unexpected invoke: " << invoke;
2822 }
2823 break;
2824 default:
2825 LOG(FATAL) << "Unexpected return type: " << type;
2826 result_check = nullptr;
2827 }
2828 if (sc.Check(soa, false, result_check, &result)) {
2829 return result;
2830 }
2831 }
2832 result.J = 0;
2833 return result;
2834 }
2835
2836 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2837 jmethodID mid, va_list vargs, Primitive::Type type,
2838 InvokeType invoke) {
2839 ScopedObjectAccess soa(env);
2840 ScopedCheck sc(kFlag_Default, function_name);
2841 JniValueType result;
2842 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke) &&
2843 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2844 const char* result_check;
2845 switch (type) {
2846 case Primitive::kPrimNot:
2847 result_check = "L";
2848 switch (invoke) {
2849 case kVirtual:
2850 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
2851 break;
2852 case kDirect:
2853 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
2854 break;
2855 case kStatic:
2856 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
2857 break;
2858 default:
2859 LOG(FATAL) << "Unexpected invoke: " << invoke;
2860 }
2861 break;
2862 case Primitive::kPrimBoolean:
2863 result_check = "Z";
2864 switch (invoke) {
2865 case kVirtual:
2866 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
2867 break;
2868 case kDirect:
2869 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
2870 break;
2871 case kStatic:
2872 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
2873 break;
2874 default:
2875 LOG(FATAL) << "Unexpected invoke: " << invoke;
2876 }
2877 break;
2878 case Primitive::kPrimByte:
2879 result_check = "B";
2880 switch (invoke) {
2881 case kVirtual:
2882 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
2883 break;
2884 case kDirect:
2885 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
2886 break;
2887 case kStatic:
2888 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
2889 break;
2890 default:
2891 LOG(FATAL) << "Unexpected invoke: " << invoke;
2892 }
2893 break;
2894 case Primitive::kPrimChar:
2895 result_check = "C";
2896 switch (invoke) {
2897 case kVirtual:
2898 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
2899 break;
2900 case kDirect:
2901 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
2902 break;
2903 case kStatic:
2904 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
2905 break;
2906 default:
2907 LOG(FATAL) << "Unexpected invoke: " << invoke;
2908 }
2909 break;
2910 case Primitive::kPrimShort:
2911 result_check = "S";
2912 switch (invoke) {
2913 case kVirtual:
2914 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
2915 break;
2916 case kDirect:
2917 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
2918 break;
2919 case kStatic:
2920 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
2921 break;
2922 default:
2923 LOG(FATAL) << "Unexpected invoke: " << invoke;
2924 }
2925 break;
2926 case Primitive::kPrimInt:
2927 result_check = "I";
2928 switch (invoke) {
2929 case kVirtual:
2930 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
2931 break;
2932 case kDirect:
2933 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
2934 break;
2935 case kStatic:
2936 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
2937 break;
2938 default:
2939 LOG(FATAL) << "Unexpected invoke: " << invoke;
2940 }
2941 break;
2942 case Primitive::kPrimLong:
2943 result_check = "J";
2944 switch (invoke) {
2945 case kVirtual:
2946 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
2947 break;
2948 case kDirect:
2949 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
2950 break;
2951 case kStatic:
2952 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
2953 break;
2954 default:
2955 LOG(FATAL) << "Unexpected invoke: " << invoke;
2956 }
2957 break;
2958 case Primitive::kPrimFloat:
2959 result_check = "F";
2960 switch (invoke) {
2961 case kVirtual:
2962 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
2963 break;
2964 case kDirect:
2965 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
2966 break;
2967 case kStatic:
2968 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
2969 break;
2970 default:
2971 LOG(FATAL) << "Unexpected invoke: " << invoke;
2972 }
2973 break;
2974 case Primitive::kPrimDouble:
2975 result_check = "D";
2976 switch (invoke) {
2977 case kVirtual:
2978 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
2979 break;
2980 case kDirect:
2981 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
2982 break;
2983 case kStatic:
2984 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
2985 break;
2986 default:
2987 LOG(FATAL) << "Unexpected invoke: " << invoke;
2988 }
2989 break;
2990 case Primitive::kPrimVoid:
2991 result_check = "V";
2992 result.V = nullptr;
2993 switch (invoke) {
2994 case kVirtual:
2995 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
2996 break;
2997 case kDirect:
2998 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
2999 break;
3000 case kStatic:
3001 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3002 break;
3003 default:
3004 LOG(FATAL) << "Unexpected invoke: " << invoke;
3005 }
3006 break;
3007 default:
3008 LOG(FATAL) << "Unexpected return type: " << type;
3009 result_check = nullptr;
3010 }
3011 if (sc.Check(soa, false, result_check, &result)) {
3012 return result;
3013 }
3014 }
3015 result.J = 0;
3016 return result;
3017 }
3018
3019 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3020 jboolean* is_copy, bool utf, bool critical) {
3021 ScopedObjectAccess soa(env);
3022 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3023 ScopedCheck sc(flags, function_name);
3024 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3025 if (sc.Check(soa, true, "Esp", args)) {
3026 JniValueType result;
3027 if (utf) {
3028 CHECK(!critical);
3029 result.u = baseEnv(env)->GetStringUTFChars(env, string, is_copy);
3030 } else {
3031 if (critical) {
3032 result.p = baseEnv(env)->GetStringCritical(env, string, is_copy);
3033 } else {
3034 result.p = baseEnv(env)->GetStringChars(env, string, is_copy);
3035 }
3036 }
3037 // TODO: could we be smarter about not copying when local_is_copy?
3038 if (result.p != nullptr && soa.ForceCopy()) {
3039 if (utf) {
3040 size_t length_in_bytes = strlen(result.u) + 1;
3041 result.u =
3042 reinterpret_cast<const char*>(GuardedCopy::Create(result.u, length_in_bytes, false));
3043 } else {
3044 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3045 result.p =
3046 reinterpret_cast<const jchar*>(GuardedCopy::Create(result.p, length_in_bytes, false));
3047 }
3048 if (is_copy != nullptr) {
3049 *is_copy = JNI_TRUE;
3050 }
3051 }
3052 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3053 return utf ? result.u : result.p;
3054 }
3055 }
3056 return nullptr;
3057 }
3058
3059 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3060 const void* chars, bool utf, bool critical) {
3061 ScopedObjectAccess soa(env);
3062 int flags = kFlag_ExcepOkay | kFlag_Release;
3063 if (critical) {
3064 flags |= kFlag_CritRelease;
3065 }
3066 ScopedCheck sc(flags, function_name);
3067 sc.CheckNonNull(chars);
3068 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3069 if (force_copy_ok && soa.ForceCopy()) {
3070 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3071 }
3072 if (force_copy_ok) {
3073 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3074 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3075 if (utf) {
3076 CHECK(!critical);
3077 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3078 } else {
3079 if (critical) {
3080 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3081 } else {
3082 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3083 }
3084 }
3085 JniValueType result;
3086 sc.Check(soa, false, "V", &result);
3087 }
3088 }
3089 }
3090
3091 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3092 Primitive::Type type) {
3093 ScopedObjectAccess soa(env);
3094 ScopedCheck sc(kFlag_Default, __FUNCTION__);
3095 JniValueType args[2] = {{.E = env}, {.z = length}};
3096 if (sc.Check(soa, true, "Ez", args)) {
3097 JniValueType result;
3098 switch (type) {
3099 case Primitive::kPrimBoolean:
3100 result.a = baseEnv(env)->NewBooleanArray(env, length);
3101 break;
3102 case Primitive::kPrimByte:
3103 result.a = baseEnv(env)->NewByteArray(env, length);
3104 break;
3105 case Primitive::kPrimChar:
3106 result.a = baseEnv(env)->NewCharArray(env, length);
3107 break;
3108 case Primitive::kPrimShort:
3109 result.a = baseEnv(env)->NewShortArray(env, length);
3110 break;
3111 case Primitive::kPrimInt:
3112 result.a = baseEnv(env)->NewIntArray(env, length);
3113 break;
3114 case Primitive::kPrimLong:
3115 result.a = baseEnv(env)->NewLongArray(env, length);
3116 break;
3117 case Primitive::kPrimFloat:
3118 result.a = baseEnv(env)->NewFloatArray(env, length);
3119 break;
3120 case Primitive::kPrimDouble:
3121 result.a = baseEnv(env)->NewDoubleArray(env, length);
3122 break;
3123 default:
3124 LOG(FATAL) << "Unexpected primitive type: " << type;
3125 }
3126 if (sc.Check(soa, false, "a", &result)) {
3127 return result.a;
3128 }
3129 }
3130 return nullptr;
3131 }
3132
3133 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3134 JNIEnv* env, jarray array, jboolean* is_copy) {
3135 ScopedObjectAccess soa(env);
3136 ScopedCheck sc(kFlag_Default, function_name);
3137 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3138 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3139 JniValueType result;
3140 switch (type) {
3141 case Primitive::kPrimBoolean:
3142 result.p = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3143 is_copy);
3144 break;
3145 case Primitive::kPrimByte:
3146 result.p = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array),
3147 is_copy);
3148 break;
3149 case Primitive::kPrimChar:
3150 result.p = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array),
3151 is_copy);
3152 break;
3153 case Primitive::kPrimShort:
3154 result.p = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array),
3155 is_copy);
3156 break;
3157 case Primitive::kPrimInt:
3158 result.p = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
3159 break;
3160 case Primitive::kPrimLong:
3161 result.p = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array),
3162 is_copy);
3163 break;
3164 case Primitive::kPrimFloat:
3165 result.p = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array),
3166 is_copy);
3167 break;
3168 case Primitive::kPrimDouble:
3169 result.p = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3170 is_copy);
3171 break;
3172 default:
3173 LOG(FATAL) << "Unexpected primitive type: " << type;
3174 }
3175 if (result.p != nullptr && soa.ForceCopy()) {
3176 result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
3177 if (is_copy != nullptr) {
3178 *is_copy = JNI_TRUE;
3179 }
3180 }
3181 if (sc.Check(soa, false, "p", &result)) {
3182 return const_cast<void*>(result.p);
3183 }
3184 }
3185 return nullptr;
3186 }
3187
3188 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3189 JNIEnv* env, jarray array, void* elems, jint mode) {
3190 ScopedObjectAccess soa(env);
3191 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3192 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3193 if (soa.ForceCopy()) {
3194 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3195 }
3196 if (!soa.ForceCopy() || elems != nullptr) {
3197 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3198 if (sc.Check(soa, true, "Eapr", args)) {
3199 switch (type) {
3200 case Primitive::kPrimBoolean:
3201 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3202 reinterpret_cast<jboolean*>(elems), mode);
3203 break;
3204 case Primitive::kPrimByte:
3205 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3206 reinterpret_cast<jbyte*>(elems), mode);
3207 break;
3208 case Primitive::kPrimChar:
3209 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3210 reinterpret_cast<jchar*>(elems), mode);
3211 break;
3212 case Primitive::kPrimShort:
3213 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3214 reinterpret_cast<jshort*>(elems), mode);
3215 break;
3216 case Primitive::kPrimInt:
3217 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3218 reinterpret_cast<jint*>(elems), mode);
3219 break;
3220 case Primitive::kPrimLong:
3221 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3222 reinterpret_cast<jlong*>(elems), mode);
3223 break;
3224 case Primitive::kPrimFloat:
3225 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3226 reinterpret_cast<jfloat*>(elems), mode);
3227 break;
3228 case Primitive::kPrimDouble:
3229 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3230 reinterpret_cast<jdouble*>(elems), mode);
3231 break;
3232 default:
3233 LOG(FATAL) << "Unexpected primitive type: " << type;
3234 }
3235 JniValueType result;
3236 result.V = nullptr;
3237 sc.Check(soa, false, "V", &result);
3238 }
3239 }
3240 }
3241 }
3242
3243 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3244 jarray array, jsize start, jsize len, void* buf) {
3245 ScopedObjectAccess soa(env);
3246 ScopedCheck sc(kFlag_Default, function_name);
3247 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3248 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3249 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3250 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3251 switch (type) {
3252 case Primitive::kPrimBoolean:
3253 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3254 reinterpret_cast<jboolean*>(buf));
3255 break;
3256 case Primitive::kPrimByte:
3257 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3258 reinterpret_cast<jbyte*>(buf));
3259 break;
3260 case Primitive::kPrimChar:
3261 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3262 reinterpret_cast<jchar*>(buf));
3263 break;
3264 case Primitive::kPrimShort:
3265 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3266 reinterpret_cast<jshort*>(buf));
3267 break;
3268 case Primitive::kPrimInt:
3269 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3270 reinterpret_cast<jint*>(buf));
3271 break;
3272 case Primitive::kPrimLong:
3273 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3274 reinterpret_cast<jlong*>(buf));
3275 break;
3276 case Primitive::kPrimFloat:
3277 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3278 reinterpret_cast<jfloat*>(buf));
3279 break;
3280 case Primitive::kPrimDouble:
3281 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3282 reinterpret_cast<jdouble*>(buf));
3283 break;
3284 default:
3285 LOG(FATAL) << "Unexpected primitive type: " << type;
3286 }
3287 JniValueType result;
3288 result.V = nullptr;
3289 sc.Check(soa, false, "V", &result);
3290 }
3291 }
3292
3293 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3294 jarray array, jsize start, jsize len, const void* buf) {
3295 ScopedObjectAccess soa(env);
3296 ScopedCheck sc(kFlag_Default, function_name);
3297 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3298 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3299 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3300 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3301 switch (type) {
3302 case Primitive::kPrimBoolean:
3303 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3304 reinterpret_cast<const jboolean*>(buf));
3305 break;
3306 case Primitive::kPrimByte:
3307 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3308 reinterpret_cast<const jbyte*>(buf));
3309 break;
3310 case Primitive::kPrimChar:
3311 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3312 reinterpret_cast<const jchar*>(buf));
3313 break;
3314 case Primitive::kPrimShort:
3315 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3316 reinterpret_cast<const jshort*>(buf));
3317 break;
3318 case Primitive::kPrimInt:
3319 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3320 reinterpret_cast<const jint*>(buf));
3321 break;
3322 case Primitive::kPrimLong:
3323 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3324 reinterpret_cast<const jlong*>(buf));
3325 break;
3326 case Primitive::kPrimFloat:
3327 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3328 reinterpret_cast<const jfloat*>(buf));
3329 break;
3330 case Primitive::kPrimDouble:
3331 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3332 reinterpret_cast<const jdouble*>(buf));
3333 break;
3334 default:
3335 LOG(FATAL) << "Unexpected primitive type: " << type;
3336 }
3337 JniValueType result;
3338 result.V = nullptr;
3339 sc.Check(soa, false, "V", &result);
3340 }
3341 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003342};
3343
3344const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003345 nullptr, // reserved0.
3346 nullptr, // reserved1.
3347 nullptr, // reserved2.
3348 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003349 CheckJNI::GetVersion,
3350 CheckJNI::DefineClass,
3351 CheckJNI::FindClass,
3352 CheckJNI::FromReflectedMethod,
3353 CheckJNI::FromReflectedField,
3354 CheckJNI::ToReflectedMethod,
3355 CheckJNI::GetSuperclass,
3356 CheckJNI::IsAssignableFrom,
3357 CheckJNI::ToReflectedField,
3358 CheckJNI::Throw,
3359 CheckJNI::ThrowNew,
3360 CheckJNI::ExceptionOccurred,
3361 CheckJNI::ExceptionDescribe,
3362 CheckJNI::ExceptionClear,
3363 CheckJNI::FatalError,
3364 CheckJNI::PushLocalFrame,
3365 CheckJNI::PopLocalFrame,
3366 CheckJNI::NewGlobalRef,
3367 CheckJNI::DeleteGlobalRef,
3368 CheckJNI::DeleteLocalRef,
3369 CheckJNI::IsSameObject,
3370 CheckJNI::NewLocalRef,
3371 CheckJNI::EnsureLocalCapacity,
3372 CheckJNI::AllocObject,
3373 CheckJNI::NewObject,
3374 CheckJNI::NewObjectV,
3375 CheckJNI::NewObjectA,
3376 CheckJNI::GetObjectClass,
3377 CheckJNI::IsInstanceOf,
3378 CheckJNI::GetMethodID,
3379 CheckJNI::CallObjectMethod,
3380 CheckJNI::CallObjectMethodV,
3381 CheckJNI::CallObjectMethodA,
3382 CheckJNI::CallBooleanMethod,
3383 CheckJNI::CallBooleanMethodV,
3384 CheckJNI::CallBooleanMethodA,
3385 CheckJNI::CallByteMethod,
3386 CheckJNI::CallByteMethodV,
3387 CheckJNI::CallByteMethodA,
3388 CheckJNI::CallCharMethod,
3389 CheckJNI::CallCharMethodV,
3390 CheckJNI::CallCharMethodA,
3391 CheckJNI::CallShortMethod,
3392 CheckJNI::CallShortMethodV,
3393 CheckJNI::CallShortMethodA,
3394 CheckJNI::CallIntMethod,
3395 CheckJNI::CallIntMethodV,
3396 CheckJNI::CallIntMethodA,
3397 CheckJNI::CallLongMethod,
3398 CheckJNI::CallLongMethodV,
3399 CheckJNI::CallLongMethodA,
3400 CheckJNI::CallFloatMethod,
3401 CheckJNI::CallFloatMethodV,
3402 CheckJNI::CallFloatMethodA,
3403 CheckJNI::CallDoubleMethod,
3404 CheckJNI::CallDoubleMethodV,
3405 CheckJNI::CallDoubleMethodA,
3406 CheckJNI::CallVoidMethod,
3407 CheckJNI::CallVoidMethodV,
3408 CheckJNI::CallVoidMethodA,
3409 CheckJNI::CallNonvirtualObjectMethod,
3410 CheckJNI::CallNonvirtualObjectMethodV,
3411 CheckJNI::CallNonvirtualObjectMethodA,
3412 CheckJNI::CallNonvirtualBooleanMethod,
3413 CheckJNI::CallNonvirtualBooleanMethodV,
3414 CheckJNI::CallNonvirtualBooleanMethodA,
3415 CheckJNI::CallNonvirtualByteMethod,
3416 CheckJNI::CallNonvirtualByteMethodV,
3417 CheckJNI::CallNonvirtualByteMethodA,
3418 CheckJNI::CallNonvirtualCharMethod,
3419 CheckJNI::CallNonvirtualCharMethodV,
3420 CheckJNI::CallNonvirtualCharMethodA,
3421 CheckJNI::CallNonvirtualShortMethod,
3422 CheckJNI::CallNonvirtualShortMethodV,
3423 CheckJNI::CallNonvirtualShortMethodA,
3424 CheckJNI::CallNonvirtualIntMethod,
3425 CheckJNI::CallNonvirtualIntMethodV,
3426 CheckJNI::CallNonvirtualIntMethodA,
3427 CheckJNI::CallNonvirtualLongMethod,
3428 CheckJNI::CallNonvirtualLongMethodV,
3429 CheckJNI::CallNonvirtualLongMethodA,
3430 CheckJNI::CallNonvirtualFloatMethod,
3431 CheckJNI::CallNonvirtualFloatMethodV,
3432 CheckJNI::CallNonvirtualFloatMethodA,
3433 CheckJNI::CallNonvirtualDoubleMethod,
3434 CheckJNI::CallNonvirtualDoubleMethodV,
3435 CheckJNI::CallNonvirtualDoubleMethodA,
3436 CheckJNI::CallNonvirtualVoidMethod,
3437 CheckJNI::CallNonvirtualVoidMethodV,
3438 CheckJNI::CallNonvirtualVoidMethodA,
3439 CheckJNI::GetFieldID,
3440 CheckJNI::GetObjectField,
3441 CheckJNI::GetBooleanField,
3442 CheckJNI::GetByteField,
3443 CheckJNI::GetCharField,
3444 CheckJNI::GetShortField,
3445 CheckJNI::GetIntField,
3446 CheckJNI::GetLongField,
3447 CheckJNI::GetFloatField,
3448 CheckJNI::GetDoubleField,
3449 CheckJNI::SetObjectField,
3450 CheckJNI::SetBooleanField,
3451 CheckJNI::SetByteField,
3452 CheckJNI::SetCharField,
3453 CheckJNI::SetShortField,
3454 CheckJNI::SetIntField,
3455 CheckJNI::SetLongField,
3456 CheckJNI::SetFloatField,
3457 CheckJNI::SetDoubleField,
3458 CheckJNI::GetStaticMethodID,
3459 CheckJNI::CallStaticObjectMethod,
3460 CheckJNI::CallStaticObjectMethodV,
3461 CheckJNI::CallStaticObjectMethodA,
3462 CheckJNI::CallStaticBooleanMethod,
3463 CheckJNI::CallStaticBooleanMethodV,
3464 CheckJNI::CallStaticBooleanMethodA,
3465 CheckJNI::CallStaticByteMethod,
3466 CheckJNI::CallStaticByteMethodV,
3467 CheckJNI::CallStaticByteMethodA,
3468 CheckJNI::CallStaticCharMethod,
3469 CheckJNI::CallStaticCharMethodV,
3470 CheckJNI::CallStaticCharMethodA,
3471 CheckJNI::CallStaticShortMethod,
3472 CheckJNI::CallStaticShortMethodV,
3473 CheckJNI::CallStaticShortMethodA,
3474 CheckJNI::CallStaticIntMethod,
3475 CheckJNI::CallStaticIntMethodV,
3476 CheckJNI::CallStaticIntMethodA,
3477 CheckJNI::CallStaticLongMethod,
3478 CheckJNI::CallStaticLongMethodV,
3479 CheckJNI::CallStaticLongMethodA,
3480 CheckJNI::CallStaticFloatMethod,
3481 CheckJNI::CallStaticFloatMethodV,
3482 CheckJNI::CallStaticFloatMethodA,
3483 CheckJNI::CallStaticDoubleMethod,
3484 CheckJNI::CallStaticDoubleMethodV,
3485 CheckJNI::CallStaticDoubleMethodA,
3486 CheckJNI::CallStaticVoidMethod,
3487 CheckJNI::CallStaticVoidMethodV,
3488 CheckJNI::CallStaticVoidMethodA,
3489 CheckJNI::GetStaticFieldID,
3490 CheckJNI::GetStaticObjectField,
3491 CheckJNI::GetStaticBooleanField,
3492 CheckJNI::GetStaticByteField,
3493 CheckJNI::GetStaticCharField,
3494 CheckJNI::GetStaticShortField,
3495 CheckJNI::GetStaticIntField,
3496 CheckJNI::GetStaticLongField,
3497 CheckJNI::GetStaticFloatField,
3498 CheckJNI::GetStaticDoubleField,
3499 CheckJNI::SetStaticObjectField,
3500 CheckJNI::SetStaticBooleanField,
3501 CheckJNI::SetStaticByteField,
3502 CheckJNI::SetStaticCharField,
3503 CheckJNI::SetStaticShortField,
3504 CheckJNI::SetStaticIntField,
3505 CheckJNI::SetStaticLongField,
3506 CheckJNI::SetStaticFloatField,
3507 CheckJNI::SetStaticDoubleField,
3508 CheckJNI::NewString,
3509 CheckJNI::GetStringLength,
3510 CheckJNI::GetStringChars,
3511 CheckJNI::ReleaseStringChars,
3512 CheckJNI::NewStringUTF,
3513 CheckJNI::GetStringUTFLength,
3514 CheckJNI::GetStringUTFChars,
3515 CheckJNI::ReleaseStringUTFChars,
3516 CheckJNI::GetArrayLength,
3517 CheckJNI::NewObjectArray,
3518 CheckJNI::GetObjectArrayElement,
3519 CheckJNI::SetObjectArrayElement,
3520 CheckJNI::NewBooleanArray,
3521 CheckJNI::NewByteArray,
3522 CheckJNI::NewCharArray,
3523 CheckJNI::NewShortArray,
3524 CheckJNI::NewIntArray,
3525 CheckJNI::NewLongArray,
3526 CheckJNI::NewFloatArray,
3527 CheckJNI::NewDoubleArray,
3528 CheckJNI::GetBooleanArrayElements,
3529 CheckJNI::GetByteArrayElements,
3530 CheckJNI::GetCharArrayElements,
3531 CheckJNI::GetShortArrayElements,
3532 CheckJNI::GetIntArrayElements,
3533 CheckJNI::GetLongArrayElements,
3534 CheckJNI::GetFloatArrayElements,
3535 CheckJNI::GetDoubleArrayElements,
3536 CheckJNI::ReleaseBooleanArrayElements,
3537 CheckJNI::ReleaseByteArrayElements,
3538 CheckJNI::ReleaseCharArrayElements,
3539 CheckJNI::ReleaseShortArrayElements,
3540 CheckJNI::ReleaseIntArrayElements,
3541 CheckJNI::ReleaseLongArrayElements,
3542 CheckJNI::ReleaseFloatArrayElements,
3543 CheckJNI::ReleaseDoubleArrayElements,
3544 CheckJNI::GetBooleanArrayRegion,
3545 CheckJNI::GetByteArrayRegion,
3546 CheckJNI::GetCharArrayRegion,
3547 CheckJNI::GetShortArrayRegion,
3548 CheckJNI::GetIntArrayRegion,
3549 CheckJNI::GetLongArrayRegion,
3550 CheckJNI::GetFloatArrayRegion,
3551 CheckJNI::GetDoubleArrayRegion,
3552 CheckJNI::SetBooleanArrayRegion,
3553 CheckJNI::SetByteArrayRegion,
3554 CheckJNI::SetCharArrayRegion,
3555 CheckJNI::SetShortArrayRegion,
3556 CheckJNI::SetIntArrayRegion,
3557 CheckJNI::SetLongArrayRegion,
3558 CheckJNI::SetFloatArrayRegion,
3559 CheckJNI::SetDoubleArrayRegion,
3560 CheckJNI::RegisterNatives,
3561 CheckJNI::UnregisterNatives,
3562 CheckJNI::MonitorEnter,
3563 CheckJNI::MonitorExit,
3564 CheckJNI::GetJavaVM,
3565 CheckJNI::GetStringRegion,
3566 CheckJNI::GetStringUTFRegion,
3567 CheckJNI::GetPrimitiveArrayCritical,
3568 CheckJNI::ReleasePrimitiveArrayCritical,
3569 CheckJNI::GetStringCritical,
3570 CheckJNI::ReleaseStringCritical,
3571 CheckJNI::NewWeakGlobalRef,
3572 CheckJNI::DeleteWeakGlobalRef,
3573 CheckJNI::ExceptionCheck,
3574 CheckJNI::NewDirectByteBuffer,
3575 CheckJNI::GetDirectBufferAddress,
3576 CheckJNI::GetDirectBufferCapacity,
3577 CheckJNI::GetObjectRefType,
3578};
3579
3580const JNINativeInterface* GetCheckJniNativeInterface() {
3581 return &gCheckNativeInterface;
3582}
3583
3584class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003585 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003586 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003587 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3588 JniValueType args[1] = {{.v = vm}};
3589 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3590 JniValueType result;
3591 result.i = BaseVm(vm)->DestroyJavaVM(vm);
3592 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3593 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003594 }
3595
3596 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003597 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3598 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3599 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3600 JniValueType result;
3601 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3602 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3603 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003604 }
3605
3606 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003607 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3608 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3609 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3610 JniValueType result;
3611 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3612 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3613 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003614 }
3615
3616 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003617 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3618 JniValueType args[1] = {{.v = vm}};
3619 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3620 JniValueType result;
3621 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3622 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3623 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003624 }
3625
Ian Rogers68d8b422014-07-17 11:09:10 -07003626 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3627 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3628 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3629 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3630 JniValueType result;
3631 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3632 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3633 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003634 }
3635
3636 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003637 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3638 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003639 }
3640};
3641
3642const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003643 nullptr, // reserved0
3644 nullptr, // reserved1
3645 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003646 CheckJII::DestroyJavaVM,
3647 CheckJII::AttachCurrentThread,
3648 CheckJII::DetachCurrentThread,
3649 CheckJII::GetEnv,
3650 CheckJII::AttachCurrentThreadAsDaemon
3651};
3652
3653const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3654 return &gCheckInvokeInterface;
3655}
3656
3657} // namespace art