1 /*
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
22 #include "base/logging.h"
23 #include "class_linker.h"
24 #include "class_linker-inl.h"
25 #include "dex_file-inl.h"
26 #include "gc/space/space.h"
27 #include "mirror/art_field-inl.h"
28 #include "mirror/art_method-inl.h"
29 #include "mirror/class-inl.h"
30 #include "mirror/object-inl.h"
31 #include "mirror/object_array-inl.h"
32 #include "mirror/throwable.h"
33 #include "object_utils.h"
34 #include "runtime.h"
35 #include "scoped_thread_state_change.h"
36 #include "thread.h"
37
38 namespace art {
39
JniAbort(const char * jni_function_name,const char * msg)40 static void JniAbort(const char* jni_function_name, const char* msg) {
41 Thread* self = Thread::Current();
42 ScopedObjectAccess soa(self);
43 mirror::ArtMethod* current_method = self->GetCurrentMethod(NULL);
44
45 std::ostringstream os;
46 os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
47
48 if (jni_function_name != NULL) {
49 os << "\n in call to " << jni_function_name;
50 }
51 // TODO: is this useful given that we're about to dump the calling thread's stack?
52 if (current_method != NULL) {
53 os << "\n from " << PrettyMethod(current_method);
54 }
55 os << "\n";
56 self->Dump(os);
57
58 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
59 if (vm->check_jni_abort_hook != NULL) {
60 vm->check_jni_abort_hook(vm->check_jni_abort_hook_data, os.str());
61 } else {
62 // Ensure that we get a native stack trace for this thread.
63 self->TransitionFromRunnableToSuspended(kNative);
64 LOG(FATAL) << os.str();
65 self->TransitionFromSuspendedToRunnable(); // Unreachable, keep annotalysis happy.
66 }
67 }
68
JniAbortV(const char * jni_function_name,const char * fmt,va_list ap)69 static void JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) {
70 std::string msg;
71 StringAppendV(&msg, fmt, ap);
72 JniAbort(jni_function_name, msg.c_str());
73 }
74
JniAbortF(const char * jni_function_name,const char * fmt,...)75 void JniAbortF(const char* jni_function_name, const char* fmt, ...) {
76 va_list args;
77 va_start(args, fmt);
78 JniAbortV(jni_function_name, fmt, args);
79 va_end(args);
80 }
81
82 /*
83 * ===========================================================================
84 * JNI function helpers
85 * ===========================================================================
86 */
87
IsSirtLocalRef(JNIEnv * env,jobject localRef)88 static bool IsSirtLocalRef(JNIEnv* env, jobject localRef) {
89 return GetIndirectRefKind(localRef) == kSirtOrInvalid &&
90 reinterpret_cast<JNIEnvExt*>(env)->self->SirtContains(localRef);
91 }
92
93 // Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
94 // The code deliberately uses an invalid sequence of operations, so we
95 // need to pass it through unmodified. Review that code before making
96 // any changes here.
97 #define kNoCopyMagic 0xd5aab57f
98
99 // Flags passed into ScopedCheck.
100 #define kFlag_Default 0x0000
101
102 #define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
103 #define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
104 #define kFlag_CritGet 0x0002 // This is a critical "get".
105 #define kFlag_CritRelease 0x0003 // This is a critical "release".
106 #define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
107
108 #define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
109 #define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
110
111 #define kFlag_Release 0x0010 // Are we in a non-critical release function?
112 #define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
113
114 #define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
115
116 #define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
117
118 static const char* gBuiltInPrefixes[] = {
119 "Landroid/",
120 "Lcom/android/",
121 "Lcom/google/android/",
122 "Ldalvik/",
123 "Ljava/",
124 "Ljavax/",
125 "Llibcore/",
126 "Lorg/apache/harmony/",
127 NULL
128 };
129
ShouldTrace(JavaVMExt * vm,const mirror::ArtMethod * method)130 static bool ShouldTrace(JavaVMExt* vm, const mirror::ArtMethod* method)
131 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
132 // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
133 // when a native method that matches the -Xjnitrace argument calls a JNI function
134 // such as NewByteArray.
135 // If -verbose:third-party-jni is on, we want to log any JNI function calls
136 // made by a third-party native method.
137 std::string class_name(MethodHelper(method).GetDeclaringClassDescriptor());
138 if (!vm->trace.empty() && class_name.find(vm->trace) != std::string::npos) {
139 return true;
140 }
141 if (VLOG_IS_ON(third_party_jni)) {
142 // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
143 // like part of Android.
144 for (size_t i = 0; gBuiltInPrefixes[i] != NULL; ++i) {
145 if (StartsWith(class_name, gBuiltInPrefixes[i])) {
146 return false;
147 }
148 }
149 return true;
150 }
151 return false;
152 }
153
154 class ScopedCheck {
155 public:
156 // For JNIEnv* functions.
ScopedCheck(JNIEnv * env,int flags,const char * functionName)157 explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName)
158 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
159 : soa_(env) {
160 Init(flags, functionName, true);
161 CheckThread(flags);
162 }
163
164 // For JavaVM* functions.
165 // TODO: it's not correct that this is a lock function, but making it so aids annotalysis.
ScopedCheck(JavaVM * vm,bool has_method,const char * functionName)166 explicit ScopedCheck(JavaVM* vm, bool has_method, const char* functionName)
167 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
168 : soa_(vm) {
169 Init(kFlag_Invocation, functionName, has_method);
170 }
171
UNLOCK_FUNCTION(Locks::mutator_lock_)172 ~ScopedCheck() UNLOCK_FUNCTION(Locks::mutator_lock_) {}
173
soa()174 const ScopedObjectAccess& soa() {
175 return soa_;
176 }
177
ForceCopy()178 bool ForceCopy() {
179 return Runtime::Current()->GetJavaVM()->force_copy;
180 }
181
182 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
183 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
184 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
185 // circumstances, but this is incorrect.
CheckClassName(const char * class_name)186 void CheckClassName(const char* class_name) {
187 if (!IsValidJniClassName(class_name)) {
188 JniAbortF(function_name_,
189 "illegal class name '%s'\n"
190 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
191 class_name);
192 }
193 }
194
195 /*
196 * Verify that the field is of the appropriate type. If the field has an
197 * object type, "java_object" is the object we're trying to assign into it.
198 *
199 * Works for both static and instance fields.
200 */
CheckFieldType(jobject java_object,jfieldID fid,char prim,bool isStatic)201 void CheckFieldType(jobject java_object, jfieldID fid, char prim, bool isStatic)
202 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
203 mirror::ArtField* f = CheckFieldID(fid);
204 if (f == NULL) {
205 return;
206 }
207 mirror::Class* field_type = FieldHelper(f).GetType();
208 if (!field_type->IsPrimitive()) {
209 if (java_object != NULL) {
210 mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
211 // If java_object is a weak global ref whose referent has been cleared,
212 // obj will be NULL. Otherwise, obj should always be non-NULL
213 // and valid.
214 if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
215 Runtime::Current()->GetHeap()->DumpSpaces();
216 JniAbortF(function_name_, "field operation on invalid %s: %p",
217 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
218 return;
219 } else {
220 if (!obj->InstanceOf(field_type)) {
221 JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %s",
222 PrettyField(f).c_str(), PrettyTypeOf(obj).c_str());
223 return;
224 }
225 }
226 }
227 } else if (field_type != Runtime::Current()->GetClassLinker()->FindPrimitiveClass(prim)) {
228 JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %c",
229 PrettyField(f).c_str(), prim);
230 return;
231 }
232
233 if (isStatic != f->IsStatic()) {
234 if (isStatic) {
235 JniAbortF(function_name_, "accessing non-static field %s as static", PrettyField(f).c_str());
236 } else {
237 JniAbortF(function_name_, "accessing static field %s as non-static", PrettyField(f).c_str());
238 }
239 return;
240 }
241 }
242
243 /*
244 * Verify that this instance field ID is valid for this object.
245 *
246 * Assumes "jobj" has already been validated.
247 */
CheckInstanceFieldID(jobject java_object,jfieldID fid)248 void CheckInstanceFieldID(jobject java_object, jfieldID fid)
249 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
250 mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
251 if (o == NULL || !Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
252 Runtime::Current()->GetHeap()->DumpSpaces();
253 JniAbortF(function_name_, "field operation on invalid %s: %p",
254 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
255 return;
256 }
257
258 mirror::ArtField* f = CheckFieldID(fid);
259 if (f == NULL) {
260 return;
261 }
262 mirror::Class* c = o->GetClass();
263 FieldHelper fh(f);
264 if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == NULL) {
265 JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s",
266 PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
267 }
268 }
269
270 /*
271 * Verify that the pointer value is non-NULL.
272 */
CheckNonNull(const void * ptr)273 void CheckNonNull(const void* ptr) {
274 if (ptr == NULL) {
275 JniAbortF(function_name_, "non-nullable argument was NULL");
276 }
277 }
278
279 /*
280 * Verify that the method's return type matches the type of call.
281 * 'expectedType' will be "L" for all objects, including arrays.
282 */
CheckSig(jmethodID mid,const char * expectedType,bool isStatic)283 void CheckSig(jmethodID mid, const char* expectedType, bool isStatic)
284 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
285 mirror::ArtMethod* m = CheckMethodID(mid);
286 if (m == NULL) {
287 return;
288 }
289 if (*expectedType != MethodHelper(m).GetShorty()[0]) {
290 JniAbortF(function_name_, "the return type of %s does not match %s",
291 function_name_, PrettyMethod(m).c_str());
292 }
293 if (isStatic != m->IsStatic()) {
294 if (isStatic) {
295 JniAbortF(function_name_, "calling non-static method %s with %s",
296 PrettyMethod(m).c_str(), function_name_);
297 } else {
298 JniAbortF(function_name_, "calling static method %s with %s",
299 PrettyMethod(m).c_str(), function_name_);
300 }
301 }
302 }
303
304 /*
305 * Verify that this static field ID is valid for this class.
306 *
307 * Assumes "java_class" has already been validated.
308 */
CheckStaticFieldID(jclass java_class,jfieldID fid)309 void CheckStaticFieldID(jclass java_class, jfieldID fid)
310 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
311 mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
312 const mirror::ArtField* f = CheckFieldID(fid);
313 if (f == NULL) {
314 return;
315 }
316 if (f->GetDeclaringClass() != c) {
317 JniAbortF(function_name_, "static jfieldID %p not valid for class %s",
318 fid, PrettyClass(c).c_str());
319 }
320 }
321
322 /*
323 * Verify that "mid" is appropriate for "java_class".
324 *
325 * A mismatch isn't dangerous, because the jmethodID defines the class. In
326 * fact, java_class is unused in the implementation. It's best if we don't
327 * allow bad code in the system though.
328 *
329 * Instances of "java_class" must be instances of the method's declaring class.
330 */
CheckStaticMethod(jclass java_class,jmethodID mid)331 void CheckStaticMethod(jclass java_class, jmethodID mid)
332 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
333 const mirror::ArtMethod* m = CheckMethodID(mid);
334 if (m == NULL) {
335 return;
336 }
337 mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
338 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
339 JniAbortF(function_name_, "can't call static %s on class %s",
340 PrettyMethod(m).c_str(), PrettyClass(c).c_str());
341 }
342 }
343
344 /*
345 * Verify that "mid" is appropriate for "jobj".
346 *
347 * Make sure the object is an instance of the method's declaring class.
348 * (Note the mid might point to a declaration in an interface; this
349 * will be handled automatically by the instanceof check.)
350 */
CheckVirtualMethod(jobject java_object,jmethodID mid)351 void CheckVirtualMethod(jobject java_object, jmethodID mid)
352 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
353 const mirror::ArtMethod* m = CheckMethodID(mid);
354 if (m == NULL) {
355 return;
356 }
357 mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
358 if (!o->InstanceOf(m->GetDeclaringClass())) {
359 JniAbortF(function_name_, "can't call %s on instance of %s",
360 PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
361 }
362 }
363
364 /**
365 * The format string is a sequence of the following characters,
366 * and must be followed by arguments of the corresponding types
367 * in the same order.
368 *
369 * Java primitive types:
370 * B - jbyte
371 * C - jchar
372 * D - jdouble
373 * F - jfloat
374 * I - jint
375 * J - jlong
376 * S - jshort
377 * Z - jboolean (shown as true and false)
378 * V - void
379 *
380 * Java reference types:
381 * L - jobject
382 * a - jarray
383 * c - jclass
384 * s - jstring
385 *
386 * JNI types:
387 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
388 * f - jfieldID
389 * m - jmethodID
390 * p - void*
391 * r - jint (for release mode arguments)
392 * u - const char* (Modified UTF-8)
393 * z - jsize (for lengths; use i if negative values are okay)
394 * v - JavaVM*
395 * E - JNIEnv*
396 * . - no argument; just print "..." (used for varargs JNI calls)
397 *
398 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
399 */
Check(bool entry,const char * fmt0,...)400 void Check(bool entry, const char* fmt0, ...) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
401 va_list ap;
402
403 const mirror::ArtMethod* traceMethod = NULL;
404 if (has_method_ && (!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni))) {
405 // We need to guard some of the invocation interface's calls: a bad caller might
406 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
407 Thread* self = Thread::Current();
408 if ((flags_ & kFlag_Invocation) == 0 || self != NULL) {
409 traceMethod = self->GetCurrentMethod(NULL);
410 }
411 }
412
413 if (((flags_ & kFlag_ForceTrace) != 0) || (traceMethod != NULL && ShouldTrace(soa_.Vm(), traceMethod))) {
414 va_start(ap, fmt0);
415 std::string msg;
416 for (const char* fmt = fmt0; *fmt;) {
417 char ch = *fmt++;
418 if (ch == 'B') { // jbyte
419 jbyte b = va_arg(ap, int);
420 if (b >= 0 && b < 10) {
421 StringAppendF(&msg, "%d", b);
422 } else {
423 StringAppendF(&msg, "%#x (%d)", b, b);
424 }
425 } else if (ch == 'C') { // jchar
426 jchar c = va_arg(ap, int);
427 if (c < 0x7f && c >= ' ') {
428 StringAppendF(&msg, "U+%x ('%c')", c, c);
429 } else {
430 StringAppendF(&msg, "U+%x", c);
431 }
432 } else if (ch == 'F' || ch == 'D') { // jfloat, jdouble
433 StringAppendF(&msg, "%g", va_arg(ap, double));
434 } else if (ch == 'I' || ch == 'S') { // jint, jshort
435 StringAppendF(&msg, "%d", va_arg(ap, int));
436 } else if (ch == 'J') { // jlong
437 StringAppendF(&msg, "%lld", va_arg(ap, jlong));
438 } else if (ch == 'Z') { // jboolean
439 StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false");
440 } else if (ch == 'V') { // void
441 msg += "void";
442 } else if (ch == 'v') { // JavaVM*
443 JavaVM* vm = va_arg(ap, JavaVM*);
444 StringAppendF(&msg, "(JavaVM*)%p", vm);
445 } else if (ch == 'E') { // JNIEnv*
446 JNIEnv* env = va_arg(ap, JNIEnv*);
447 StringAppendF(&msg, "(JNIEnv*)%p", env);
448 } else if (ch == 'L' || ch == 'a' || ch == 's') { // jobject, jarray, jstring
449 // For logging purposes, these are identical.
450 jobject o = va_arg(ap, jobject);
451 if (o == NULL) {
452 msg += "NULL";
453 } else {
454 StringAppendF(&msg, "%p", o);
455 }
456 } else if (ch == 'b') { // jboolean (JNI-style)
457 jboolean b = va_arg(ap, int);
458 msg += (b ? "JNI_TRUE" : "JNI_FALSE");
459 } else if (ch == 'c') { // jclass
460 jclass jc = va_arg(ap, jclass);
461 mirror::Class* c = reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(jc));
462 if (c == NULL) {
463 msg += "NULL";
464 } else if (c == kInvalidIndirectRefObject || !Runtime::Current()->GetHeap()->IsHeapAddress(c)) {
465 StringAppendF(&msg, "INVALID POINTER:%p", jc);
466 } else if (!c->IsClass()) {
467 msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
468 } else {
469 msg += PrettyClass(c);
470 if (!entry) {
471 StringAppendF(&msg, " (%p)", jc);
472 }
473 }
474 } else if (ch == 'f') { // jfieldID
475 jfieldID fid = va_arg(ap, jfieldID);
476 mirror::ArtField* f = reinterpret_cast<mirror::ArtField*>(fid);
477 msg += PrettyField(f);
478 if (!entry) {
479 StringAppendF(&msg, " (%p)", fid);
480 }
481 } else if (ch == 'z') { // non-negative jsize
482 // You might expect jsize to be size_t, but it's not; it's the same as jint.
483 // We only treat this specially so we can do the non-negative check.
484 // TODO: maybe this wasn't worth it?
485 jint i = va_arg(ap, jint);
486 StringAppendF(&msg, "%d", i);
487 } else if (ch == 'm') { // jmethodID
488 jmethodID mid = va_arg(ap, jmethodID);
489 mirror::ArtMethod* m = reinterpret_cast<mirror::ArtMethod*>(mid);
490 msg += PrettyMethod(m);
491 if (!entry) {
492 StringAppendF(&msg, " (%p)", mid);
493 }
494 } else if (ch == 'p') { // void* ("pointer")
495 void* p = va_arg(ap, void*);
496 if (p == NULL) {
497 msg += "NULL";
498 } else {
499 StringAppendF(&msg, "(void*) %p", p);
500 }
501 } else if (ch == 'r') { // jint (release mode)
502 jint releaseMode = va_arg(ap, jint);
503 if (releaseMode == 0) {
504 msg += "0";
505 } else if (releaseMode == JNI_ABORT) {
506 msg += "JNI_ABORT";
507 } else if (releaseMode == JNI_COMMIT) {
508 msg += "JNI_COMMIT";
509 } else {
510 StringAppendF(&msg, "invalid release mode %d", releaseMode);
511 }
512 } else if (ch == 'u') { // const char* (Modified UTF-8)
513 const char* utf = va_arg(ap, const char*);
514 if (utf == NULL) {
515 msg += "NULL";
516 } else {
517 StringAppendF(&msg, "\"%s\"", utf);
518 }
519 } else if (ch == '.') {
520 msg += "...";
521 } else {
522 JniAbortF(function_name_, "unknown trace format specifier: %c", ch);
523 return;
524 }
525 if (*fmt) {
526 StringAppendF(&msg, ", ");
527 }
528 }
529 va_end(ap);
530
531 if ((flags_ & kFlag_ForceTrace) != 0) {
532 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
533 } else if (entry) {
534 if (has_method_) {
535 std::string methodName(PrettyMethod(traceMethod, false));
536 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
537 indent_ = methodName.size() + 1;
538 } else {
539 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
540 indent_ = 0;
541 }
542 } else {
543 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
544 }
545 }
546
547 // We always do the thorough checks on entry, and never on exit...
548 if (entry) {
549 va_start(ap, fmt0);
550 for (const char* fmt = fmt0; *fmt; ++fmt) {
551 char ch = *fmt;
552 if (ch == 'a') {
553 CheckArray(va_arg(ap, jarray));
554 } else if (ch == 'c') {
555 CheckInstance(kClass, va_arg(ap, jclass));
556 } else if (ch == 'L') {
557 CheckObject(va_arg(ap, jobject));
558 } else if (ch == 'r') {
559 CheckReleaseMode(va_arg(ap, jint));
560 } else if (ch == 's') {
561 CheckInstance(kString, va_arg(ap, jstring));
562 } else if (ch == 'u') {
563 if ((flags_ & kFlag_Release) != 0) {
564 CheckNonNull(va_arg(ap, const char*));
565 } else {
566 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
567 CheckUtfString(va_arg(ap, const char*), nullable);
568 }
569 } else if (ch == 'z') {
570 CheckLengthPositive(va_arg(ap, jsize));
571 } else if (strchr("BCISZbfmpEv", ch) != NULL) {
572 va_arg(ap, uint32_t); // Skip this argument.
573 } else if (ch == 'D' || ch == 'F') {
574 va_arg(ap, double); // Skip this argument.
575 } else if (ch == 'J') {
576 va_arg(ap, uint64_t); // Skip this argument.
577 } else if (ch == '.') {
578 } else {
579 LOG(FATAL) << "Unknown check format specifier: " << ch;
580 }
581 }
582 va_end(ap);
583 }
584 }
585
586 enum InstanceKind {
587 kClass,
588 kDirectByteBuffer,
589 kObject,
590 kString,
591 kThrowable,
592 };
593
594 /*
595 * Verify that "jobj" is a valid non-NULL object reference, and points to
596 * an instance of expectedClass.
597 *
598 * Because we're looking at an object on the GC heap, we have to switch
599 * to "running" mode before doing the checks.
600 */
CheckInstance(InstanceKind kind,jobject java_object)601 bool CheckInstance(InstanceKind kind, jobject java_object)
602 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
603 const char* what = NULL;
604 switch (kind) {
605 case kClass:
606 what = "jclass";
607 break;
608 case kDirectByteBuffer:
609 what = "direct ByteBuffer";
610 break;
611 case kObject:
612 what = "jobject";
613 break;
614 case kString:
615 what = "jstring";
616 break;
617 case kThrowable:
618 what = "jthrowable";
619 break;
620 default:
621 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
622 }
623
624 if (java_object == NULL) {
625 JniAbortF(function_name_, "%s received null %s", function_name_, what);
626 return false;
627 }
628
629 mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
630 if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
631 Runtime::Current()->GetHeap()->DumpSpaces();
632 JniAbortF(function_name_, "%s is an invalid %s: %p (%p)",
633 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object, obj);
634 return false;
635 }
636
637 bool okay = true;
638 switch (kind) {
639 case kClass:
640 okay = obj->IsClass();
641 break;
642 case kDirectByteBuffer:
643 UNIMPLEMENTED(FATAL);
644 break;
645 case kString:
646 okay = obj->GetClass()->IsStringClass();
647 break;
648 case kThrowable:
649 okay = obj->GetClass()->IsThrowableClass();
650 break;
651 case kObject:
652 break;
653 }
654 if (!okay) {
655 JniAbortF(function_name_, "%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
656 return false;
657 }
658
659 return true;
660 }
661
662 private:
663 // Set "has_method" to true if we have a valid thread with a method pointer.
664 // We won't have one before attaching a thread, after detaching a thread, or
665 // when shutting down the runtime.
Init(int flags,const char * functionName,bool has_method)666 void Init(int flags, const char* functionName, bool has_method) {
667 flags_ = flags;
668 function_name_ = functionName;
669 has_method_ = has_method;
670 }
671
672 /*
673 * Verify that "array" is non-NULL and points to an Array object.
674 *
675 * Since we're dealing with objects, switch to "running" mode.
676 */
CheckArray(jarray java_array)677 void CheckArray(jarray java_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
678 if (java_array == NULL) {
679 JniAbortF(function_name_, "jarray was NULL");
680 return;
681 }
682
683 mirror::Array* a = soa_.Decode<mirror::Array*>(java_array);
684 if (!Runtime::Current()->GetHeap()->IsHeapAddress(a)) {
685 Runtime::Current()->GetHeap()->DumpSpaces();
686 JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)",
687 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), java_array, a);
688 } else if (!a->IsArrayInstance()) {
689 JniAbortF(function_name_, "jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
690 }
691 }
692
CheckLengthPositive(jsize length)693 void CheckLengthPositive(jsize length) {
694 if (length < 0) {
695 JniAbortF(function_name_, "negative jsize: %d", length);
696 }
697 }
698
CheckFieldID(jfieldID fid)699 mirror::ArtField* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
700 if (fid == NULL) {
701 JniAbortF(function_name_, "jfieldID was NULL");
702 return NULL;
703 }
704 mirror::ArtField* f = soa_.DecodeField(fid);
705 if (!Runtime::Current()->GetHeap()->IsHeapAddress(f) || !f->IsArtField()) {
706 Runtime::Current()->GetHeap()->DumpSpaces();
707 JniAbortF(function_name_, "invalid jfieldID: %p", fid);
708 return NULL;
709 }
710 return f;
711 }
712
CheckMethodID(jmethodID mid)713 mirror::ArtMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
714 if (mid == NULL) {
715 JniAbortF(function_name_, "jmethodID was NULL");
716 return NULL;
717 }
718 mirror::ArtMethod* m = soa_.DecodeMethod(mid);
719 if (!Runtime::Current()->GetHeap()->IsHeapAddress(m) || !m->IsArtMethod()) {
720 Runtime::Current()->GetHeap()->DumpSpaces();
721 JniAbortF(function_name_, "invalid jmethodID: %p", mid);
722 return NULL;
723 }
724 return m;
725 }
726
727 /*
728 * Verify that "jobj" is a valid object, and that it's an object that JNI
729 * is allowed to know about. We allow NULL references.
730 *
731 * Switches to "running" mode before performing checks.
732 */
CheckObject(jobject java_object)733 void CheckObject(jobject java_object)
734 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
735 if (java_object == NULL) {
736 return;
737 }
738
739 mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
740 if (!Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
741 Runtime::Current()->GetHeap()->DumpSpaces();
742 // TODO: when we remove work_around_app_jni_bugs, this should be impossible.
743 JniAbortF(function_name_, "native code passing in reference to invalid %s: %p",
744 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
745 }
746 }
747
748 /*
749 * Verify that the "mode" argument passed to a primitive array Release
750 * function is one of the valid values.
751 */
CheckReleaseMode(jint mode)752 void CheckReleaseMode(jint mode) {
753 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
754 JniAbortF(function_name_, "unknown value for release mode: %d", mode);
755 }
756 }
757
CheckThread(int flags)758 void CheckThread(int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
759 Thread* self = Thread::Current();
760 if (self == NULL) {
761 JniAbortF(function_name_, "a thread (tid %d) is making JNI calls without being attached", GetTid());
762 return;
763 }
764
765 // Get the *correct* JNIEnv by going through our TLS pointer.
766 JNIEnvExt* threadEnv = self->GetJniEnv();
767
768 // Verify that the current thread is (a) attached and (b) associated with
769 // this particular instance of JNIEnv.
770 if (soa_.Env() != threadEnv) {
771 if (soa_.Vm()->work_around_app_jni_bugs) {
772 // If we're keeping broken code limping along, we need to suppress the abort...
773 LOG(ERROR) << "APP BUG DETECTED: thread " << *self << " using JNIEnv* from thread " << *soa_.Self();
774 } else {
775 JniAbortF(function_name_, "thread %s using JNIEnv* from thread %s",
776 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*soa_.Self()).c_str());
777 return;
778 }
779 }
780
781 // Verify that, if this thread previously made a critical "get" call, we
782 // do the corresponding "release" call before we try anything else.
783 switch (flags & kFlag_CritMask) {
784 case kFlag_CritOkay: // okay to call this method
785 break;
786 case kFlag_CritBad: // not okay to call
787 if (threadEnv->critical) {
788 JniAbortF(function_name_, "thread %s using JNI after critical get", ToStr<Thread>(*self).c_str());
789 return;
790 }
791 break;
792 case kFlag_CritGet: // this is a "get" call
793 // Don't check here; we allow nested gets.
794 threadEnv->critical++;
795 break;
796 case kFlag_CritRelease: // this is a "release" call
797 threadEnv->critical--;
798 if (threadEnv->critical < 0) {
799 JniAbortF(function_name_, "thread %s called too many critical releases", ToStr<Thread>(*self).c_str());
800 return;
801 }
802 break;
803 default:
804 LOG(FATAL) << "Bad flags (internal error): " << flags;
805 }
806
807 // Verify that, if an exception has been raised, the native code doesn't
808 // make any JNI calls other than the Exception* methods.
809 if ((flags & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
810 ThrowLocation throw_location;
811 mirror::Throwable* exception = self->GetException(&throw_location);
812 std::string type(PrettyTypeOf(exception));
813 JniAbortF(function_name_, "JNI %s called with pending exception '%s' thrown in %s",
814 function_name_, type.c_str(), throw_location.Dump().c_str());
815 return;
816 }
817 }
818
819 // Verifies that "bytes" points to valid Modified UTF-8 data.
CheckUtfString(const char * bytes,bool nullable)820 void CheckUtfString(const char* bytes, bool nullable) {
821 if (bytes == NULL) {
822 if (!nullable) {
823 JniAbortF(function_name_, "non-nullable const char* was NULL");
824 return;
825 }
826 return;
827 }
828
829 const char* errorKind = NULL;
830 uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
831 if (errorKind != NULL) {
832 JniAbortF(function_name_,
833 "input is not valid Modified UTF-8: illegal %s byte %#x\n"
834 " string: '%s'", errorKind, utf8, bytes);
835 return;
836 }
837 }
838
CheckUtfBytes(const char * bytes,const char ** errorKind)839 static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
840 while (*bytes != '\0') {
841 uint8_t utf8 = *(bytes++);
842 // Switch on the high four bits.
843 switch (utf8 >> 4) {
844 case 0x00:
845 case 0x01:
846 case 0x02:
847 case 0x03:
848 case 0x04:
849 case 0x05:
850 case 0x06:
851 case 0x07:
852 // Bit pattern 0xxx. No need for any extra bytes.
853 break;
854 case 0x08:
855 case 0x09:
856 case 0x0a:
857 case 0x0b:
858 case 0x0f:
859 /*
860 * Bit pattern 10xx or 1111, which are illegal start bytes.
861 * Note: 1111 is valid for normal UTF-8, but not the
862 * Modified UTF-8 used here.
863 */
864 *errorKind = "start";
865 return utf8;
866 case 0x0e:
867 // Bit pattern 1110, so there are two additional bytes.
868 utf8 = *(bytes++);
869 if ((utf8 & 0xc0) != 0x80) {
870 *errorKind = "continuation";
871 return utf8;
872 }
873 // Fall through to take care of the final byte.
874 case 0x0c:
875 case 0x0d:
876 // Bit pattern 110x, so there is one additional byte.
877 utf8 = *(bytes++);
878 if ((utf8 & 0xc0) != 0x80) {
879 *errorKind = "continuation";
880 return utf8;
881 }
882 break;
883 }
884 }
885 return 0;
886 }
887
888 const ScopedObjectAccess soa_;
889 const char* function_name_;
890 int flags_;
891 bool has_method_;
892 int indent_;
893
894 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
895 };
896
897 #define CHECK_JNI_ENTRY(flags, types, args...) \
898 ScopedCheck sc(env, flags, __FUNCTION__); \
899 sc.Check(true, types, ##args)
900
901 #define CHECK_JNI_EXIT(type, exp) ({ \
902 auto _rc = (exp); \
903 sc.Check(false, type, _rc); \
904 _rc; })
905 #define CHECK_JNI_EXIT_VOID() \
906 sc.Check(false, "V")
907
908 /*
909 * ===========================================================================
910 * Guarded arrays
911 * ===========================================================================
912 */
913
914 #define kGuardLen 512 /* must be multiple of 2 */
915 #define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
916 #define kGuardMagic 0xffd5aa96
917
918 /* this gets tucked in at the start of the buffer; struct size must be even */
919 struct GuardedCopy {
920 uint32_t magic;
921 uLong adler;
922 size_t original_length;
923 const void* original_ptr;
924
925 /* find the GuardedCopy given the pointer into the "live" data */
FromDataart::GuardedCopy926 static inline const GuardedCopy* FromData(const void* dataBuf) {
927 return reinterpret_cast<const GuardedCopy*>(ActualBuffer(dataBuf));
928 }
929
930 /*
931 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
932 * filling in the area around it with guard data.
933 *
934 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
935 */
Createart::GuardedCopy936 static void* Create(const void* buf, size_t len, bool modOkay) {
937 size_t newLen = ActualLength(len);
938 uint8_t* newBuf = DebugAlloc(newLen);
939
940 // Fill it in with a pattern.
941 uint16_t* pat = reinterpret_cast<uint16_t*>(newBuf);
942 for (size_t i = 0; i < newLen / 2; i++) {
943 *pat++ = kGuardPattern;
944 }
945
946 // Copy the data in; note "len" could be zero.
947 memcpy(newBuf + kGuardLen / 2, buf, len);
948
949 // If modification is not expected, grab a checksum.
950 uLong adler = 0;
951 if (!modOkay) {
952 adler = adler32(0L, Z_NULL, 0);
953 adler = adler32(adler, reinterpret_cast<const Bytef*>(buf), len);
954 *reinterpret_cast<uLong*>(newBuf) = adler;
955 }
956
957 GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf);
958 pExtra->magic = kGuardMagic;
959 pExtra->adler = adler;
960 pExtra->original_ptr = buf;
961 pExtra->original_length = len;
962
963 return newBuf + kGuardLen / 2;
964 }
965
966 /*
967 * Free up the guard buffer, scrub it, and return the original pointer.
968 */
Destroyart::GuardedCopy969 static void* Destroy(void* dataBuf) {
970 const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
971 void* original_ptr = const_cast<void*>(pExtra->original_ptr);
972 size_t len = pExtra->original_length;
973 DebugFree(dataBuf, len);
974 return original_ptr;
975 }
976
977 /*
978 * Verify the guard area and, if "modOkay" is false, that the data itself
979 * has not been altered.
980 *
981 * The caller has already checked that "dataBuf" is non-NULL.
982 */
Checkart::GuardedCopy983 static void Check(const char* functionName, const void* dataBuf, bool modOkay) {
984 static const uint32_t kMagicCmp = kGuardMagic;
985 const uint8_t* fullBuf = ActualBuffer(dataBuf);
986 const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
987
988 // Before we do anything with "pExtra", check the magic number. We
989 // do the check with memcmp rather than "==" in case the pointer is
990 // unaligned. If it points to completely bogus memory we're going
991 // to crash, but there's no easy way around that.
992 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
993 uint8_t buf[4];
994 memcpy(buf, &pExtra->magic, 4);
995 JniAbortF(functionName,
996 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
997 buf[3], buf[2], buf[1], buf[0], dataBuf); // Assumes little-endian.
998 }
999
1000 size_t len = pExtra->original_length;
1001
1002 // Check bottom half of guard; skip over optional checksum storage.
1003 const uint16_t* pat = reinterpret_cast<const uint16_t*>(fullBuf);
1004 for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
1005 if (pat[i] != kGuardPattern) {
1006 JniAbortF(functionName, "guard pattern(1) disturbed at %p +%d", fullBuf, i*2);
1007 }
1008 }
1009
1010 int offset = kGuardLen / 2 + len;
1011 if (offset & 0x01) {
1012 // Odd byte; expected value depends on endian.
1013 const uint16_t patSample = kGuardPattern;
1014 uint8_t expected_byte = reinterpret_cast<const uint8_t*>(&patSample)[1];
1015 if (fullBuf[offset] != expected_byte) {
1016 JniAbortF(functionName, "guard pattern disturbed in odd byte after %p +%d 0x%02x 0x%02x",
1017 fullBuf, offset, fullBuf[offset], expected_byte);
1018 }
1019 offset++;
1020 }
1021
1022 // Check top half of guard.
1023 pat = reinterpret_cast<const uint16_t*>(fullBuf + offset);
1024 for (size_t i = 0; i < kGuardLen / 4; i++) {
1025 if (pat[i] != kGuardPattern) {
1026 JniAbortF(functionName, "guard pattern(2) disturbed at %p +%d", fullBuf, offset + i*2);
1027 }
1028 }
1029
1030 // If modification is not expected, verify checksum. Strictly speaking
1031 // this is wrong: if we told the client that we made a copy, there's no
1032 // reason they can't alter the buffer.
1033 if (!modOkay) {
1034 uLong adler = adler32(0L, Z_NULL, 0);
1035 adler = adler32(adler, (const Bytef*)dataBuf, len);
1036 if (pExtra->adler != adler) {
1037 JniAbortF(functionName, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1038 pExtra->adler, adler, dataBuf);
1039 }
1040 }
1041 }
1042
1043 private:
DebugAllocart::GuardedCopy1044 static uint8_t* DebugAlloc(size_t len) {
1045 void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1046 if (result == MAP_FAILED) {
1047 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1048 }
1049 return reinterpret_cast<uint8_t*>(result);
1050 }
1051
DebugFreeart::GuardedCopy1052 static void DebugFree(void* dataBuf, size_t len) {
1053 uint8_t* fullBuf = ActualBuffer(dataBuf);
1054 size_t totalByteCount = ActualLength(len);
1055 // TODO: we could mprotect instead, and keep the allocation around for a while.
1056 // This would be even more expensive, but it might catch more errors.
1057 // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) {
1058 // PLOG(WARNING) << "mprotect(PROT_NONE) failed";
1059 // }
1060 if (munmap(fullBuf, totalByteCount) != 0) {
1061 PLOG(FATAL) << "munmap(" << reinterpret_cast<void*>(fullBuf) << ", " << totalByteCount << ") failed";
1062 }
1063 }
1064
ActualBufferart::GuardedCopy1065 static const uint8_t* ActualBuffer(const void* dataBuf) {
1066 return reinterpret_cast<const uint8_t*>(dataBuf) - kGuardLen / 2;
1067 }
1068
ActualBufferart::GuardedCopy1069 static uint8_t* ActualBuffer(void* dataBuf) {
1070 return reinterpret_cast<uint8_t*>(dataBuf) - kGuardLen / 2;
1071 }
1072
1073 // Underlying length of a user allocation of 'length' bytes.
ActualLengthart::GuardedCopy1074 static size_t ActualLength(size_t length) {
1075 return (length + kGuardLen + 1) & ~0x01;
1076 }
1077 };
1078
1079 /*
1080 * Create a guarded copy of a primitive array. Modifications to the copied
1081 * data are allowed. Returns a pointer to the copied data.
1082 */
CreateGuardedPACopy(JNIEnv * env,const jarray java_array,jboolean * isCopy)1083 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* isCopy) {
1084 ScopedObjectAccess soa(env);
1085
1086 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1087 size_t component_size = a->GetClass()->GetComponentSize();
1088 size_t byte_count = a->GetLength() * component_size;
1089 void* result = GuardedCopy::Create(a->GetRawData(component_size), byte_count, true);
1090 if (isCopy != NULL) {
1091 *isCopy = JNI_TRUE;
1092 }
1093 return result;
1094 }
1095
1096 /*
1097 * Perform the array "release" operation, which may or may not copy data
1098 * back into the managed heap, and may or may not release the underlying storage.
1099 */
ReleaseGuardedPACopy(JNIEnv * env,jarray java_array,void * dataBuf,int mode)1100 static void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, int mode) {
1101 if (reinterpret_cast<uintptr_t>(dataBuf) == kNoCopyMagic) {
1102 return;
1103 }
1104
1105 ScopedObjectAccess soa(env);
1106 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1107
1108 GuardedCopy::Check(__FUNCTION__, dataBuf, true);
1109
1110 if (mode != JNI_ABORT) {
1111 size_t len = GuardedCopy::FromData(dataBuf)->original_length;
1112 memcpy(a->GetRawData(a->GetClass()->GetComponentSize()), dataBuf, len);
1113 }
1114 if (mode != JNI_COMMIT) {
1115 GuardedCopy::Destroy(dataBuf);
1116 }
1117 }
1118
1119 /*
1120 * ===========================================================================
1121 * JNI functions
1122 * ===========================================================================
1123 */
1124
1125 class CheckJNI {
1126 public:
GetVersion(JNIEnv * env)1127 static jint GetVersion(JNIEnv* env) {
1128 CHECK_JNI_ENTRY(kFlag_Default, "E", env);
1129 return CHECK_JNI_EXIT("I", baseEnv(env)->GetVersion(env));
1130 }
1131
DefineClass(JNIEnv * env,const char * name,jobject loader,const jbyte * buf,jsize bufLen)1132 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, jsize bufLen) {
1133 CHECK_JNI_ENTRY(kFlag_Default, "EuLpz", env, name, loader, buf, bufLen);
1134 sc.CheckClassName(name);
1135 return CHECK_JNI_EXIT("c", baseEnv(env)->DefineClass(env, name, loader, buf, bufLen));
1136 }
1137
FindClass(JNIEnv * env,const char * name)1138 static jclass FindClass(JNIEnv* env, const char* name) {
1139 CHECK_JNI_ENTRY(kFlag_Default, "Eu", env, name);
1140 sc.CheckClassName(name);
1141 return CHECK_JNI_EXIT("c", baseEnv(env)->FindClass(env, name));
1142 }
1143
GetSuperclass(JNIEnv * env,jclass c)1144 static jclass GetSuperclass(JNIEnv* env, jclass c) {
1145 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1146 return CHECK_JNI_EXIT("c", baseEnv(env)->GetSuperclass(env, c));
1147 }
1148
IsAssignableFrom(JNIEnv * env,jclass c1,jclass c2)1149 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1150 CHECK_JNI_ENTRY(kFlag_Default, "Ecc", env, c1, c2);
1151 return CHECK_JNI_EXIT("b", baseEnv(env)->IsAssignableFrom(env, c1, c2));
1152 }
1153
FromReflectedMethod(JNIEnv * env,jobject method)1154 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1155 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, method);
1156 // TODO: check that 'field' is a java.lang.reflect.Method.
1157 return CHECK_JNI_EXIT("m", baseEnv(env)->FromReflectedMethod(env, method));
1158 }
1159
FromReflectedField(JNIEnv * env,jobject field)1160 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1161 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, field);
1162 // TODO: check that 'field' is a java.lang.reflect.Field.
1163 return CHECK_JNI_EXIT("f", baseEnv(env)->FromReflectedField(env, field));
1164 }
1165
ToReflectedMethod(JNIEnv * env,jclass cls,jmethodID mid,jboolean isStatic)1166 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1167 CHECK_JNI_ENTRY(kFlag_Default, "Ecmb", env, cls, mid, isStatic);
1168 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic));
1169 }
1170
ToReflectedField(JNIEnv * env,jclass cls,jfieldID fid,jboolean isStatic)1171 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1172 CHECK_JNI_ENTRY(kFlag_Default, "Ecfb", env, cls, fid, isStatic);
1173 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedField(env, cls, fid, isStatic));
1174 }
1175
Throw(JNIEnv * env,jthrowable obj)1176 static jint Throw(JNIEnv* env, jthrowable obj) {
1177 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1178 // TODO: check that 'obj' is a java.lang.Throwable.
1179 return CHECK_JNI_EXIT("I", baseEnv(env)->Throw(env, obj));
1180 }
1181
ThrowNew(JNIEnv * env,jclass c,const char * message)1182 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
1183 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Ecu", env, c, message);
1184 return CHECK_JNI_EXIT("I", baseEnv(env)->ThrowNew(env, c, message));
1185 }
1186
ExceptionOccurred(JNIEnv * env)1187 static jthrowable ExceptionOccurred(JNIEnv* env) {
1188 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1189 return CHECK_JNI_EXIT("L", baseEnv(env)->ExceptionOccurred(env));
1190 }
1191
ExceptionDescribe(JNIEnv * env)1192 static void ExceptionDescribe(JNIEnv* env) {
1193 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1194 baseEnv(env)->ExceptionDescribe(env);
1195 CHECK_JNI_EXIT_VOID();
1196 }
1197
ExceptionClear(JNIEnv * env)1198 static void ExceptionClear(JNIEnv* env) {
1199 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1200 baseEnv(env)->ExceptionClear(env);
1201 CHECK_JNI_EXIT_VOID();
1202 }
1203
FatalError(JNIEnv * env,const char * msg)1204 static void FatalError(JNIEnv* env, const char* msg) {
1205 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1206 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1207 // and it's not unimaginable that you don't know that you do. So we allow it.
1208 CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_NullableUtf, "Eu", env, msg);
1209 baseEnv(env)->FatalError(env, msg);
1210 CHECK_JNI_EXIT_VOID();
1211 }
1212
PushLocalFrame(JNIEnv * env,jint capacity)1213 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
1214 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EI", env, capacity);
1215 return CHECK_JNI_EXIT("I", baseEnv(env)->PushLocalFrame(env, capacity));
1216 }
1217
PopLocalFrame(JNIEnv * env,jobject res)1218 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
1219 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, res);
1220 return CHECK_JNI_EXIT("L", baseEnv(env)->PopLocalFrame(env, res));
1221 }
1222
NewGlobalRef(JNIEnv * env,jobject obj)1223 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
1224 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1225 return CHECK_JNI_EXIT("L", baseEnv(env)->NewGlobalRef(env, obj));
1226 }
1227
NewLocalRef(JNIEnv * env,jobject ref)1228 static jobject NewLocalRef(JNIEnv* env, jobject ref) {
1229 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, ref);
1230 return CHECK_JNI_EXIT("L", baseEnv(env)->NewLocalRef(env, ref));
1231 }
1232
DeleteGlobalRef(JNIEnv * env,jobject globalRef)1233 static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
1234 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef);
1235 if (globalRef != NULL && GetIndirectRefKind(globalRef) != kGlobal) {
1236 JniAbortF(__FUNCTION__, "DeleteGlobalRef on %s: %p",
1237 ToStr<IndirectRefKind>(GetIndirectRefKind(globalRef)).c_str(), globalRef);
1238 } else {
1239 baseEnv(env)->DeleteGlobalRef(env, globalRef);
1240 CHECK_JNI_EXIT_VOID();
1241 }
1242 }
1243
DeleteWeakGlobalRef(JNIEnv * env,jweak weakGlobalRef)1244 static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) {
1245 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef);
1246 if (weakGlobalRef != NULL && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
1247 JniAbortF(__FUNCTION__, "DeleteWeakGlobalRef on %s: %p",
1248 ToStr<IndirectRefKind>(GetIndirectRefKind(weakGlobalRef)).c_str(), weakGlobalRef);
1249 } else {
1250 baseEnv(env)->DeleteWeakGlobalRef(env, weakGlobalRef);
1251 CHECK_JNI_EXIT_VOID();
1252 }
1253 }
1254
DeleteLocalRef(JNIEnv * env,jobject localRef)1255 static void DeleteLocalRef(JNIEnv* env, jobject localRef) {
1256 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef);
1257 if (localRef != NULL && GetIndirectRefKind(localRef) != kLocal && !IsSirtLocalRef(env, localRef)) {
1258 JniAbortF(__FUNCTION__, "DeleteLocalRef on %s: %p",
1259 ToStr<IndirectRefKind>(GetIndirectRefKind(localRef)).c_str(), localRef);
1260 } else {
1261 baseEnv(env)->DeleteLocalRef(env, localRef);
1262 CHECK_JNI_EXIT_VOID();
1263 }
1264 }
1265
EnsureLocalCapacity(JNIEnv * env,jint capacity)1266 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1267 CHECK_JNI_ENTRY(kFlag_Default, "EI", env, capacity);
1268 return CHECK_JNI_EXIT("I", baseEnv(env)->EnsureLocalCapacity(env, capacity));
1269 }
1270
IsSameObject(JNIEnv * env,jobject ref1,jobject ref2)1271 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1272 CHECK_JNI_ENTRY(kFlag_Default, "ELL", env, ref1, ref2);
1273 return CHECK_JNI_EXIT("b", baseEnv(env)->IsSameObject(env, ref1, ref2));
1274 }
1275
AllocObject(JNIEnv * env,jclass c)1276 static jobject AllocObject(JNIEnv* env, jclass c) {
1277 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1278 return CHECK_JNI_EXIT("L", baseEnv(env)->AllocObject(env, c));
1279 }
1280
NewObject(JNIEnv * env,jclass c,jmethodID mid,...)1281 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1282 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1283 va_list args;
1284 va_start(args, mid);
1285 jobject result = baseEnv(env)->NewObjectV(env, c, mid, args);
1286 va_end(args);
1287 return CHECK_JNI_EXIT("L", result);
1288 }
1289
NewObjectV(JNIEnv * env,jclass c,jmethodID mid,va_list args)1290 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list args) {
1291 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1292 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectV(env, c, mid, args));
1293 }
1294
NewObjectA(JNIEnv * env,jclass c,jmethodID mid,jvalue * args)1295 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) {
1296 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1297 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectA(env, c, mid, args));
1298 }
1299
GetObjectClass(JNIEnv * env,jobject obj)1300 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1301 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1302 return CHECK_JNI_EXIT("c", baseEnv(env)->GetObjectClass(env, obj));
1303 }
1304
IsInstanceOf(JNIEnv * env,jobject obj,jclass c)1305 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1306 CHECK_JNI_ENTRY(kFlag_Default, "ELc", env, obj, c);
1307 return CHECK_JNI_EXIT("b", baseEnv(env)->IsInstanceOf(env, obj, c));
1308 }
1309
GetMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)1310 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1311 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1312 return CHECK_JNI_EXIT("m", baseEnv(env)->GetMethodID(env, c, name, sig));
1313 }
1314
GetFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)1315 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1316 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1317 return CHECK_JNI_EXIT("f", baseEnv(env)->GetFieldID(env, c, name, sig));
1318 }
1319
GetStaticMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)1320 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1321 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1322 return CHECK_JNI_EXIT("m", baseEnv(env)->GetStaticMethodID(env, c, name, sig));
1323 }
1324
GetStaticFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)1325 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1326 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1327 return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, c, name, sig));
1328 }
1329
1330 #define FIELD_ACCESSORS(_ctype, _jname, _type) \
1331 static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1332 CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, c, fid); \
1333 sc.CheckStaticFieldID(c, fid); \
1334 return CHECK_JNI_EXIT(_type, baseEnv(env)->GetStatic##_jname##Field(env, c, fid)); \
1335 } \
1336 static _ctype Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1337 CHECK_JNI_ENTRY(kFlag_Default, "ELf", env, obj, fid); \
1338 sc.CheckInstanceFieldID(obj, fid); \
1339 return CHECK_JNI_EXIT(_type, baseEnv(env)->Get##_jname##Field(env, obj, fid)); \
1340 } \
1341 static void SetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid, _ctype value) { \
1342 CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, c, fid, value); \
1343 sc.CheckStaticFieldID(c, fid); \
1344 /* "value" arg only used when type == ref */ \
1345 sc.CheckFieldType((jobject)(uint32_t)value, fid, _type[0], true); \
1346 baseEnv(env)->SetStatic##_jname##Field(env, c, fid, value); \
1347 CHECK_JNI_EXIT_VOID(); \
1348 } \
1349 static void Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid, _ctype value) { \
1350 CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \
1351 sc.CheckInstanceFieldID(obj, fid); \
1352 /* "value" arg only used when type == ref */ \
1353 sc.CheckFieldType((jobject)(uint32_t) value, fid, _type[0], false); \
1354 baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \
1355 CHECK_JNI_EXIT_VOID(); \
1356 }
1357
1358 FIELD_ACCESSORS(jobject, Object, "L");
1359 FIELD_ACCESSORS(jboolean, Boolean, "Z");
1360 FIELD_ACCESSORS(jbyte, Byte, "B");
1361 FIELD_ACCESSORS(jchar, Char, "C");
1362 FIELD_ACCESSORS(jshort, Short, "S");
1363 FIELD_ACCESSORS(jint, Int, "I");
1364 FIELD_ACCESSORS(jlong, Long, "J");
1365 FIELD_ACCESSORS(jfloat, Float, "F");
1366 FIELD_ACCESSORS(jdouble, Double, "D");
1367
1368 #define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1369 /* Virtual... */ \
1370 static _ctype Call##_jname##Method(JNIEnv* env, jobject obj, \
1371 jmethodID mid, ...) \
1372 { \
1373 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1374 sc.CheckSig(mid, _retsig, false); \
1375 sc.CheckVirtualMethod(obj, mid); \
1376 _retdecl; \
1377 va_list args; \
1378 va_start(args, mid); \
1379 _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
1380 va_end(args); \
1381 _retok; \
1382 } \
1383 static _ctype Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1384 jmethodID mid, va_list args) \
1385 { \
1386 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1387 sc.CheckSig(mid, _retsig, false); \
1388 sc.CheckVirtualMethod(obj, mid); \
1389 _retdecl; \
1390 _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
1391 _retok; \
1392 } \
1393 static _ctype Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1394 jmethodID mid, jvalue* args) \
1395 { \
1396 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1397 sc.CheckSig(mid, _retsig, false); \
1398 sc.CheckVirtualMethod(obj, mid); \
1399 _retdecl; \
1400 _retasgn(baseEnv(env)->Call##_jname##MethodA(env, obj, mid, args)); \
1401 _retok; \
1402 } \
1403 /* Non-virtual... */ \
1404 static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, \
1405 jobject obj, jclass c, jmethodID mid, ...) \
1406 { \
1407 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
1408 sc.CheckSig(mid, _retsig, false); \
1409 sc.CheckVirtualMethod(obj, mid); \
1410 _retdecl; \
1411 va_list args; \
1412 va_start(args, mid); \
1413 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
1414 va_end(args); \
1415 _retok; \
1416 } \
1417 static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1418 jobject obj, jclass c, jmethodID mid, va_list args) \
1419 { \
1420 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
1421 sc.CheckSig(mid, _retsig, false); \
1422 sc.CheckVirtualMethod(obj, mid); \
1423 _retdecl; \
1424 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
1425 _retok; \
1426 } \
1427 static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1428 jobject obj, jclass c, jmethodID mid, jvalue* args) \
1429 { \
1430 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
1431 sc.CheckSig(mid, _retsig, false); \
1432 sc.CheckVirtualMethod(obj, mid); \
1433 _retdecl; \
1434 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, c, mid, args)); \
1435 _retok; \
1436 } \
1437 /* Static... */ \
1438 static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass c, jmethodID mid, ...) \
1439 { \
1440 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
1441 sc.CheckSig(mid, _retsig, true); \
1442 sc.CheckStaticMethod(c, mid); \
1443 _retdecl; \
1444 va_list args; \
1445 va_start(args, mid); \
1446 _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
1447 va_end(args); \
1448 _retok; \
1449 } \
1450 static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list args) \
1451 { \
1452 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
1453 sc.CheckSig(mid, _retsig, true); \
1454 sc.CheckStaticMethod(c, mid); \
1455 _retdecl; \
1456 _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
1457 _retok; \
1458 } \
1459 static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) \
1460 { \
1461 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
1462 sc.CheckSig(mid, _retsig, true); \
1463 sc.CheckStaticMethod(c, mid); \
1464 _retdecl; \
1465 _retasgn(baseEnv(env)->CallStatic##_jname##MethodA(env, c, mid, args)); \
1466 _retok; \
1467 }
1468
1469 #define NON_VOID_RETURN(_retsig, _ctype) return CHECK_JNI_EXIT(_retsig, (_ctype) result)
1470 #define VOID_RETURN CHECK_JNI_EXIT_VOID()
1471
1472 CALL(jobject, Object, mirror::Object* result, result = reinterpret_cast<mirror::Object*>, NON_VOID_RETURN("L", jobject), "L");
1473 CALL(jboolean, Boolean, jboolean result, result =, NON_VOID_RETURN("Z", jboolean), "Z");
1474 CALL(jbyte, Byte, jbyte result, result =, NON_VOID_RETURN("B", jbyte), "B");
1475 CALL(jchar, Char, jchar result, result =, NON_VOID_RETURN("C", jchar), "C");
1476 CALL(jshort, Short, jshort result, result =, NON_VOID_RETURN("S", jshort), "S");
1477 CALL(jint, Int, jint result, result =, NON_VOID_RETURN("I", jint), "I");
1478 CALL(jlong, Long, jlong result, result =, NON_VOID_RETURN("J", jlong), "J");
1479 CALL(jfloat, Float, jfloat result, result =, NON_VOID_RETURN("F", jfloat), "F");
1480 CALL(jdouble, Double, jdouble result, result =, NON_VOID_RETURN("D", jdouble), "D");
1481 CALL(void, Void, , , VOID_RETURN, "V");
1482
NewString(JNIEnv * env,const jchar * unicodeChars,jsize len)1483 static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
1484 CHECK_JNI_ENTRY(kFlag_Default, "Epz", env, unicodeChars, len);
1485 return CHECK_JNI_EXIT("s", baseEnv(env)->NewString(env, unicodeChars, len));
1486 }
1487
GetStringLength(JNIEnv * env,jstring string)1488 static jsize GetStringLength(JNIEnv* env, jstring string) {
1489 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1490 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringLength(env, string));
1491 }
1492
GetStringChars(JNIEnv * env,jstring java_string,jboolean * isCopy)1493 static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1494 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy);
1495 const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy);
1496 if (sc.ForceCopy() && result != NULL) {
1497 mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
1498 int byteCount = s->GetLength() * 2;
1499 result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
1500 if (isCopy != NULL) {
1501 *isCopy = JNI_TRUE;
1502 }
1503 }
1504 return CHECK_JNI_EXIT("p", result);
1505 }
1506
ReleaseStringChars(JNIEnv * env,jstring string,const jchar * chars)1507 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
1508 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Esp", env, string, chars);
1509 sc.CheckNonNull(chars);
1510 if (sc.ForceCopy()) {
1511 GuardedCopy::Check(__FUNCTION__, chars, false);
1512 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(chars)));
1513 }
1514 baseEnv(env)->ReleaseStringChars(env, string, chars);
1515 CHECK_JNI_EXIT_VOID();
1516 }
1517
NewStringUTF(JNIEnv * env,const char * bytes)1518 static jstring NewStringUTF(JNIEnv* env, const char* bytes) {
1519 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, bytes); // TODO: show pointer and truncate string.
1520 return CHECK_JNI_EXIT("s", baseEnv(env)->NewStringUTF(env, bytes));
1521 }
1522
GetStringUTFLength(JNIEnv * env,jstring string)1523 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
1524 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1525 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringUTFLength(env, string));
1526 }
1527
GetStringUTFChars(JNIEnv * env,jstring string,jboolean * isCopy)1528 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
1529 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy);
1530 const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
1531 if (sc.ForceCopy() && result != NULL) {
1532 result = (const char*) GuardedCopy::Create(result, strlen(result) + 1, false);
1533 if (isCopy != NULL) {
1534 *isCopy = JNI_TRUE;
1535 }
1536 }
1537 return CHECK_JNI_EXIT("u", result); // TODO: show pointer and truncate string.
1538 }
1539
ReleaseStringUTFChars(JNIEnv * env,jstring string,const char * utf)1540 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
1541 CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_Release, "Esu", env, string, utf); // TODO: show pointer and truncate string.
1542 if (sc.ForceCopy()) {
1543 GuardedCopy::Check(__FUNCTION__, utf, false);
1544 utf = reinterpret_cast<const char*>(GuardedCopy::Destroy(const_cast<char*>(utf)));
1545 }
1546 baseEnv(env)->ReleaseStringUTFChars(env, string, utf);
1547 CHECK_JNI_EXIT_VOID();
1548 }
1549
GetArrayLength(JNIEnv * env,jarray array)1550 static jsize GetArrayLength(JNIEnv* env, jarray array) {
1551 CHECK_JNI_ENTRY(kFlag_CritOkay, "Ea", env, array);
1552 return CHECK_JNI_EXIT("I", baseEnv(env)->GetArrayLength(env, array));
1553 }
1554
NewObjectArray(JNIEnv * env,jsize length,jclass elementClass,jobject initialElement)1555 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass elementClass, jobject initialElement) {
1556 CHECK_JNI_ENTRY(kFlag_Default, "EzcL", env, length, elementClass, initialElement);
1557 return CHECK_JNI_EXIT("a", baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement));
1558 }
1559
GetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index)1560 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
1561 CHECK_JNI_ENTRY(kFlag_Default, "EaI", env, array, index);
1562 return CHECK_JNI_EXIT("L", baseEnv(env)->GetObjectArrayElement(env, array, index));
1563 }
1564
SetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index,jobject value)1565 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
1566 CHECK_JNI_ENTRY(kFlag_Default, "EaIL", env, array, index, value);
1567 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
1568 CHECK_JNI_EXIT_VOID();
1569 }
1570
1571 #define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1572 static _artype New##_jname##Array(JNIEnv* env, jsize length) { \
1573 CHECK_JNI_ENTRY(kFlag_Default, "Ez", env, length); \
1574 return CHECK_JNI_EXIT("a", baseEnv(env)->New##_jname##Array(env, length)); \
1575 }
1576 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1577 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1578 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1579 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1580 NEW_PRIMITIVE_ARRAY(jintArray, Int);
1581 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1582 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1583 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1584
1585 struct ForceCopyGetChecker {
1586 public:
ForceCopyGetCheckerart::CheckJNI::ForceCopyGetChecker1587 ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) {
1588 force_copy = sc.ForceCopy();
1589 no_copy = 0;
1590 if (force_copy && isCopy != NULL) {
1591 // Capture this before the base call tramples on it.
1592 no_copy = *reinterpret_cast<uint32_t*>(isCopy);
1593 }
1594 }
1595
1596 template<typename ResultT>
Checkart::CheckJNI::ForceCopyGetChecker1597 ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
1598 if (force_copy && result != NULL) {
1599 if (no_copy != kNoCopyMagic) {
1600 result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
1601 }
1602 }
1603 return result;
1604 }
1605
1606 uint32_t no_copy;
1607 bool force_copy;
1608 };
1609
1610 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1611 static _ctype* Get##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, jboolean* isCopy) { \
1612 CHECK_JNI_ENTRY(kFlag_Default, "Eap", env, array, isCopy); \
1613 _ctype* result = ForceCopyGetChecker(sc, isCopy).Check(env, array, isCopy, baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy)); \
1614 return CHECK_JNI_EXIT("p", result); \
1615 }
1616
1617 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1618 static void Release##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, _ctype* elems, jint mode) { \
1619 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Eapr", env, array, elems, mode); \
1620 sc.CheckNonNull(elems); \
1621 if (sc.ForceCopy()) { \
1622 ReleaseGuardedPACopy(env, array, elems, mode); \
1623 } \
1624 baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \
1625 CHECK_JNI_EXIT_VOID(); \
1626 }
1627
1628 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1629 static void Get##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, _ctype* buf) { \
1630 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1631 baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \
1632 CHECK_JNI_EXIT_VOID(); \
1633 }
1634
1635 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1636 static void Set##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \
1637 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1638 baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \
1639 CHECK_JNI_EXIT_VOID(); \
1640 }
1641
1642 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1643 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1644 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1645 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1646 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1647
1648 // TODO: verify primitive array type matches call type.
1649 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1650 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1651 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1652 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1653 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1654 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1655 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1656 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1657
RegisterNatives(JNIEnv * env,jclass c,const JNINativeMethod * methods,jint nMethods)1658 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1659 CHECK_JNI_ENTRY(kFlag_Default, "EcpI", env, c, methods, nMethods);
1660 return CHECK_JNI_EXIT("I", baseEnv(env)->RegisterNatives(env, c, methods, nMethods));
1661 }
1662
UnregisterNatives(JNIEnv * env,jclass c)1663 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1664 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1665 return CHECK_JNI_EXIT("I", baseEnv(env)->UnregisterNatives(env, c));
1666 }
1667
MonitorEnter(JNIEnv * env,jobject obj)1668 static jint MonitorEnter(JNIEnv* env, jobject obj) {
1669 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1670 if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1671 return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already.
1672 }
1673 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorEnter(env, obj));
1674 }
1675
MonitorExit(JNIEnv * env,jobject obj)1676 static jint MonitorExit(JNIEnv* env, jobject obj) {
1677 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, obj);
1678 if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1679 return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already.
1680 }
1681 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorExit(env, obj));
1682 }
1683
GetJavaVM(JNIEnv * env,JavaVM ** vm)1684 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1685 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, vm);
1686 return CHECK_JNI_EXIT("I", baseEnv(env)->GetJavaVM(env, vm));
1687 }
1688
GetStringRegion(JNIEnv * env,jstring str,jsize start,jsize len,jchar * buf)1689 static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
1690 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1691 baseEnv(env)->GetStringRegion(env, str, start, len, buf);
1692 CHECK_JNI_EXIT_VOID();
1693 }
1694
GetStringUTFRegion(JNIEnv * env,jstring str,jsize start,jsize len,char * buf)1695 static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1696 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1697 baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf);
1698 CHECK_JNI_EXIT_VOID();
1699 }
1700
GetPrimitiveArrayCritical(JNIEnv * env,jarray array,jboolean * isCopy)1701 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
1702 CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy);
1703 void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
1704 if (sc.ForceCopy() && result != NULL) {
1705 result = CreateGuardedPACopy(env, array, isCopy);
1706 }
1707 return CHECK_JNI_EXIT("p", result);
1708 }
1709
ReleasePrimitiveArrayCritical(JNIEnv * env,jarray array,void * carray,jint mode)1710 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
1711 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Eapr", env, array, carray, mode);
1712 sc.CheckNonNull(carray);
1713 if (sc.ForceCopy()) {
1714 ReleaseGuardedPACopy(env, array, carray, mode);
1715 }
1716 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1717 CHECK_JNI_EXIT_VOID();
1718 }
1719
GetStringCritical(JNIEnv * env,jstring java_string,jboolean * isCopy)1720 static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1721 CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy);
1722 const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy);
1723 if (sc.ForceCopy() && result != NULL) {
1724 mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
1725 int byteCount = s->GetLength() * 2;
1726 result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
1727 if (isCopy != NULL) {
1728 *isCopy = JNI_TRUE;
1729 }
1730 }
1731 return CHECK_JNI_EXIT("p", result);
1732 }
1733
ReleaseStringCritical(JNIEnv * env,jstring string,const jchar * carray)1734 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) {
1735 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Esp", env, string, carray);
1736 sc.CheckNonNull(carray);
1737 if (sc.ForceCopy()) {
1738 GuardedCopy::Check(__FUNCTION__, carray, false);
1739 carray = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(carray)));
1740 }
1741 baseEnv(env)->ReleaseStringCritical(env, string, carray);
1742 CHECK_JNI_EXIT_VOID();
1743 }
1744
NewWeakGlobalRef(JNIEnv * env,jobject obj)1745 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1746 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1747 return CHECK_JNI_EXIT("L", baseEnv(env)->NewWeakGlobalRef(env, obj));
1748 }
1749
ExceptionCheck(JNIEnv * env)1750 static jboolean ExceptionCheck(JNIEnv* env) {
1751 CHECK_JNI_ENTRY(kFlag_CritOkay | kFlag_ExcepOkay, "E", env);
1752 return CHECK_JNI_EXIT("b", baseEnv(env)->ExceptionCheck(env));
1753 }
1754
GetObjectRefType(JNIEnv * env,jobject obj)1755 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1756 // Note: we use "Ep" rather than "EL" because this is the one JNI function
1757 // that it's okay to pass an invalid reference to.
1758 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, obj);
1759 // TODO: proper decoding of jobjectRefType!
1760 return CHECK_JNI_EXIT("I", baseEnv(env)->GetObjectRefType(env, obj));
1761 }
1762
NewDirectByteBuffer(JNIEnv * env,void * address,jlong capacity)1763 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
1764 CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity);
1765 if (address == NULL) {
1766 JniAbortF(__FUNCTION__, "non-nullable address is NULL");
1767 }
1768 if (capacity <= 0) {
1769 JniAbortF(__FUNCTION__, "capacity must be greater than 0: %lld", capacity);
1770 }
1771 return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity));
1772 }
1773
GetDirectBufferAddress(JNIEnv * env,jobject buf)1774 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
1775 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1776 // TODO: check that 'buf' is a java.nio.Buffer.
1777 return CHECK_JNI_EXIT("p", baseEnv(env)->GetDirectBufferAddress(env, buf));
1778 }
1779
GetDirectBufferCapacity(JNIEnv * env,jobject buf)1780 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
1781 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1782 // TODO: check that 'buf' is a java.nio.Buffer.
1783 return CHECK_JNI_EXIT("J", baseEnv(env)->GetDirectBufferCapacity(env, buf));
1784 }
1785
1786 private:
baseEnv(JNIEnv * env)1787 static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
1788 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
1789 }
1790 };
1791
1792 const JNINativeInterface gCheckNativeInterface = {
1793 NULL, // reserved0.
1794 NULL, // reserved1.
1795 NULL, // reserved2.
1796 NULL, // reserved3.
1797 CheckJNI::GetVersion,
1798 CheckJNI::DefineClass,
1799 CheckJNI::FindClass,
1800 CheckJNI::FromReflectedMethod,
1801 CheckJNI::FromReflectedField,
1802 CheckJNI::ToReflectedMethod,
1803 CheckJNI::GetSuperclass,
1804 CheckJNI::IsAssignableFrom,
1805 CheckJNI::ToReflectedField,
1806 CheckJNI::Throw,
1807 CheckJNI::ThrowNew,
1808 CheckJNI::ExceptionOccurred,
1809 CheckJNI::ExceptionDescribe,
1810 CheckJNI::ExceptionClear,
1811 CheckJNI::FatalError,
1812 CheckJNI::PushLocalFrame,
1813 CheckJNI::PopLocalFrame,
1814 CheckJNI::NewGlobalRef,
1815 CheckJNI::DeleteGlobalRef,
1816 CheckJNI::DeleteLocalRef,
1817 CheckJNI::IsSameObject,
1818 CheckJNI::NewLocalRef,
1819 CheckJNI::EnsureLocalCapacity,
1820 CheckJNI::AllocObject,
1821 CheckJNI::NewObject,
1822 CheckJNI::NewObjectV,
1823 CheckJNI::NewObjectA,
1824 CheckJNI::GetObjectClass,
1825 CheckJNI::IsInstanceOf,
1826 CheckJNI::GetMethodID,
1827 CheckJNI::CallObjectMethod,
1828 CheckJNI::CallObjectMethodV,
1829 CheckJNI::CallObjectMethodA,
1830 CheckJNI::CallBooleanMethod,
1831 CheckJNI::CallBooleanMethodV,
1832 CheckJNI::CallBooleanMethodA,
1833 CheckJNI::CallByteMethod,
1834 CheckJNI::CallByteMethodV,
1835 CheckJNI::CallByteMethodA,
1836 CheckJNI::CallCharMethod,
1837 CheckJNI::CallCharMethodV,
1838 CheckJNI::CallCharMethodA,
1839 CheckJNI::CallShortMethod,
1840 CheckJNI::CallShortMethodV,
1841 CheckJNI::CallShortMethodA,
1842 CheckJNI::CallIntMethod,
1843 CheckJNI::CallIntMethodV,
1844 CheckJNI::CallIntMethodA,
1845 CheckJNI::CallLongMethod,
1846 CheckJNI::CallLongMethodV,
1847 CheckJNI::CallLongMethodA,
1848 CheckJNI::CallFloatMethod,
1849 CheckJNI::CallFloatMethodV,
1850 CheckJNI::CallFloatMethodA,
1851 CheckJNI::CallDoubleMethod,
1852 CheckJNI::CallDoubleMethodV,
1853 CheckJNI::CallDoubleMethodA,
1854 CheckJNI::CallVoidMethod,
1855 CheckJNI::CallVoidMethodV,
1856 CheckJNI::CallVoidMethodA,
1857 CheckJNI::CallNonvirtualObjectMethod,
1858 CheckJNI::CallNonvirtualObjectMethodV,
1859 CheckJNI::CallNonvirtualObjectMethodA,
1860 CheckJNI::CallNonvirtualBooleanMethod,
1861 CheckJNI::CallNonvirtualBooleanMethodV,
1862 CheckJNI::CallNonvirtualBooleanMethodA,
1863 CheckJNI::CallNonvirtualByteMethod,
1864 CheckJNI::CallNonvirtualByteMethodV,
1865 CheckJNI::CallNonvirtualByteMethodA,
1866 CheckJNI::CallNonvirtualCharMethod,
1867 CheckJNI::CallNonvirtualCharMethodV,
1868 CheckJNI::CallNonvirtualCharMethodA,
1869 CheckJNI::CallNonvirtualShortMethod,
1870 CheckJNI::CallNonvirtualShortMethodV,
1871 CheckJNI::CallNonvirtualShortMethodA,
1872 CheckJNI::CallNonvirtualIntMethod,
1873 CheckJNI::CallNonvirtualIntMethodV,
1874 CheckJNI::CallNonvirtualIntMethodA,
1875 CheckJNI::CallNonvirtualLongMethod,
1876 CheckJNI::CallNonvirtualLongMethodV,
1877 CheckJNI::CallNonvirtualLongMethodA,
1878 CheckJNI::CallNonvirtualFloatMethod,
1879 CheckJNI::CallNonvirtualFloatMethodV,
1880 CheckJNI::CallNonvirtualFloatMethodA,
1881 CheckJNI::CallNonvirtualDoubleMethod,
1882 CheckJNI::CallNonvirtualDoubleMethodV,
1883 CheckJNI::CallNonvirtualDoubleMethodA,
1884 CheckJNI::CallNonvirtualVoidMethod,
1885 CheckJNI::CallNonvirtualVoidMethodV,
1886 CheckJNI::CallNonvirtualVoidMethodA,
1887 CheckJNI::GetFieldID,
1888 CheckJNI::GetObjectField,
1889 CheckJNI::GetBooleanField,
1890 CheckJNI::GetByteField,
1891 CheckJNI::GetCharField,
1892 CheckJNI::GetShortField,
1893 CheckJNI::GetIntField,
1894 CheckJNI::GetLongField,
1895 CheckJNI::GetFloatField,
1896 CheckJNI::GetDoubleField,
1897 CheckJNI::SetObjectField,
1898 CheckJNI::SetBooleanField,
1899 CheckJNI::SetByteField,
1900 CheckJNI::SetCharField,
1901 CheckJNI::SetShortField,
1902 CheckJNI::SetIntField,
1903 CheckJNI::SetLongField,
1904 CheckJNI::SetFloatField,
1905 CheckJNI::SetDoubleField,
1906 CheckJNI::GetStaticMethodID,
1907 CheckJNI::CallStaticObjectMethod,
1908 CheckJNI::CallStaticObjectMethodV,
1909 CheckJNI::CallStaticObjectMethodA,
1910 CheckJNI::CallStaticBooleanMethod,
1911 CheckJNI::CallStaticBooleanMethodV,
1912 CheckJNI::CallStaticBooleanMethodA,
1913 CheckJNI::CallStaticByteMethod,
1914 CheckJNI::CallStaticByteMethodV,
1915 CheckJNI::CallStaticByteMethodA,
1916 CheckJNI::CallStaticCharMethod,
1917 CheckJNI::CallStaticCharMethodV,
1918 CheckJNI::CallStaticCharMethodA,
1919 CheckJNI::CallStaticShortMethod,
1920 CheckJNI::CallStaticShortMethodV,
1921 CheckJNI::CallStaticShortMethodA,
1922 CheckJNI::CallStaticIntMethod,
1923 CheckJNI::CallStaticIntMethodV,
1924 CheckJNI::CallStaticIntMethodA,
1925 CheckJNI::CallStaticLongMethod,
1926 CheckJNI::CallStaticLongMethodV,
1927 CheckJNI::CallStaticLongMethodA,
1928 CheckJNI::CallStaticFloatMethod,
1929 CheckJNI::CallStaticFloatMethodV,
1930 CheckJNI::CallStaticFloatMethodA,
1931 CheckJNI::CallStaticDoubleMethod,
1932 CheckJNI::CallStaticDoubleMethodV,
1933 CheckJNI::CallStaticDoubleMethodA,
1934 CheckJNI::CallStaticVoidMethod,
1935 CheckJNI::CallStaticVoidMethodV,
1936 CheckJNI::CallStaticVoidMethodA,
1937 CheckJNI::GetStaticFieldID,
1938 CheckJNI::GetStaticObjectField,
1939 CheckJNI::GetStaticBooleanField,
1940 CheckJNI::GetStaticByteField,
1941 CheckJNI::GetStaticCharField,
1942 CheckJNI::GetStaticShortField,
1943 CheckJNI::GetStaticIntField,
1944 CheckJNI::GetStaticLongField,
1945 CheckJNI::GetStaticFloatField,
1946 CheckJNI::GetStaticDoubleField,
1947 CheckJNI::SetStaticObjectField,
1948 CheckJNI::SetStaticBooleanField,
1949 CheckJNI::SetStaticByteField,
1950 CheckJNI::SetStaticCharField,
1951 CheckJNI::SetStaticShortField,
1952 CheckJNI::SetStaticIntField,
1953 CheckJNI::SetStaticLongField,
1954 CheckJNI::SetStaticFloatField,
1955 CheckJNI::SetStaticDoubleField,
1956 CheckJNI::NewString,
1957 CheckJNI::GetStringLength,
1958 CheckJNI::GetStringChars,
1959 CheckJNI::ReleaseStringChars,
1960 CheckJNI::NewStringUTF,
1961 CheckJNI::GetStringUTFLength,
1962 CheckJNI::GetStringUTFChars,
1963 CheckJNI::ReleaseStringUTFChars,
1964 CheckJNI::GetArrayLength,
1965 CheckJNI::NewObjectArray,
1966 CheckJNI::GetObjectArrayElement,
1967 CheckJNI::SetObjectArrayElement,
1968 CheckJNI::NewBooleanArray,
1969 CheckJNI::NewByteArray,
1970 CheckJNI::NewCharArray,
1971 CheckJNI::NewShortArray,
1972 CheckJNI::NewIntArray,
1973 CheckJNI::NewLongArray,
1974 CheckJNI::NewFloatArray,
1975 CheckJNI::NewDoubleArray,
1976 CheckJNI::GetBooleanArrayElements,
1977 CheckJNI::GetByteArrayElements,
1978 CheckJNI::GetCharArrayElements,
1979 CheckJNI::GetShortArrayElements,
1980 CheckJNI::GetIntArrayElements,
1981 CheckJNI::GetLongArrayElements,
1982 CheckJNI::GetFloatArrayElements,
1983 CheckJNI::GetDoubleArrayElements,
1984 CheckJNI::ReleaseBooleanArrayElements,
1985 CheckJNI::ReleaseByteArrayElements,
1986 CheckJNI::ReleaseCharArrayElements,
1987 CheckJNI::ReleaseShortArrayElements,
1988 CheckJNI::ReleaseIntArrayElements,
1989 CheckJNI::ReleaseLongArrayElements,
1990 CheckJNI::ReleaseFloatArrayElements,
1991 CheckJNI::ReleaseDoubleArrayElements,
1992 CheckJNI::GetBooleanArrayRegion,
1993 CheckJNI::GetByteArrayRegion,
1994 CheckJNI::GetCharArrayRegion,
1995 CheckJNI::GetShortArrayRegion,
1996 CheckJNI::GetIntArrayRegion,
1997 CheckJNI::GetLongArrayRegion,
1998 CheckJNI::GetFloatArrayRegion,
1999 CheckJNI::GetDoubleArrayRegion,
2000 CheckJNI::SetBooleanArrayRegion,
2001 CheckJNI::SetByteArrayRegion,
2002 CheckJNI::SetCharArrayRegion,
2003 CheckJNI::SetShortArrayRegion,
2004 CheckJNI::SetIntArrayRegion,
2005 CheckJNI::SetLongArrayRegion,
2006 CheckJNI::SetFloatArrayRegion,
2007 CheckJNI::SetDoubleArrayRegion,
2008 CheckJNI::RegisterNatives,
2009 CheckJNI::UnregisterNatives,
2010 CheckJNI::MonitorEnter,
2011 CheckJNI::MonitorExit,
2012 CheckJNI::GetJavaVM,
2013 CheckJNI::GetStringRegion,
2014 CheckJNI::GetStringUTFRegion,
2015 CheckJNI::GetPrimitiveArrayCritical,
2016 CheckJNI::ReleasePrimitiveArrayCritical,
2017 CheckJNI::GetStringCritical,
2018 CheckJNI::ReleaseStringCritical,
2019 CheckJNI::NewWeakGlobalRef,
2020 CheckJNI::DeleteWeakGlobalRef,
2021 CheckJNI::ExceptionCheck,
2022 CheckJNI::NewDirectByteBuffer,
2023 CheckJNI::GetDirectBufferAddress,
2024 CheckJNI::GetDirectBufferCapacity,
2025 CheckJNI::GetObjectRefType,
2026 };
2027
GetCheckJniNativeInterface()2028 const JNINativeInterface* GetCheckJniNativeInterface() {
2029 return &gCheckNativeInterface;
2030 }
2031
2032 class CheckJII {
2033 public:
DestroyJavaVM(JavaVM * vm)2034 static jint DestroyJavaVM(JavaVM* vm) {
2035 ScopedCheck sc(vm, false, __FUNCTION__);
2036 sc.Check(true, "v", vm);
2037 return CHECK_JNI_EXIT("I", BaseVm(vm)->DestroyJavaVM(vm));
2038 }
2039
AttachCurrentThread(JavaVM * vm,JNIEnv ** p_env,void * thr_args)2040 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2041 ScopedCheck sc(vm, false, __FUNCTION__);
2042 sc.Check(true, "vpp", vm, p_env, thr_args);
2043 return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args));
2044 }
2045
AttachCurrentThreadAsDaemon(JavaVM * vm,JNIEnv ** p_env,void * thr_args)2046 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2047 ScopedCheck sc(vm, false, __FUNCTION__);
2048 sc.Check(true, "vpp", vm, p_env, thr_args);
2049 return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args));
2050 }
2051
DetachCurrentThread(JavaVM * vm)2052 static jint DetachCurrentThread(JavaVM* vm) {
2053 ScopedCheck sc(vm, true, __FUNCTION__);
2054 sc.Check(true, "v", vm);
2055 return CHECK_JNI_EXIT("I", BaseVm(vm)->DetachCurrentThread(vm));
2056 }
2057
GetEnv(JavaVM * vm,void ** env,jint version)2058 static jint GetEnv(JavaVM* vm, void** env, jint version) {
2059 ScopedCheck sc(vm, true, __FUNCTION__);
2060 sc.Check(true, "vpI", vm);
2061 return CHECK_JNI_EXIT("I", BaseVm(vm)->GetEnv(vm, env, version));
2062 }
2063
2064 private:
BaseVm(JavaVM * vm)2065 static inline const JNIInvokeInterface* BaseVm(JavaVM* vm) {
2066 return reinterpret_cast<JavaVMExt*>(vm)->unchecked_functions;
2067 }
2068 };
2069
2070 const JNIInvokeInterface gCheckInvokeInterface = {
2071 NULL, // reserved0
2072 NULL, // reserved1
2073 NULL, // reserved2
2074 CheckJII::DestroyJavaVM,
2075 CheckJII::AttachCurrentThread,
2076 CheckJII::DetachCurrentThread,
2077 CheckJII::GetEnv,
2078 CheckJII::AttachCurrentThreadAsDaemon
2079 };
2080
GetCheckJniInvokeInterface()2081 const JNIInvokeInterface* GetCheckJniInvokeInterface() {
2082 return &gCheckInvokeInterface;
2083 }
2084
2085 } // namespace art
2086