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