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 "check_jni.h" 18 19 #include <sys/mman.h> 20 #include <zlib.h> 21 22 #include <iomanip> 23 24 #include <android-base/logging.h> 25 #include <android-base/stringprintf.h> 26 27 #include "art_field-inl.h" 28 #include "art_method-inl.h" 29 #include "base/macros.h" 30 #include "base/to_str.h" 31 #include "base/time_utils.h" 32 #include "class_linker-inl.h" 33 #include "class_linker.h" 34 #include "class_root.h" 35 #include "dex/descriptors_names.h" 36 #include "dex/dex_file-inl.h" 37 #include "gc/space/space.h" 38 #include "java_vm_ext.h" 39 #include "jni_internal.h" 40 #include "mirror/class-inl.h" 41 #include "mirror/field.h" 42 #include "mirror/method.h" 43 #include "mirror/object-inl.h" 44 #include "mirror/object_array-inl.h" 45 #include "mirror/string-inl.h" 46 #include "mirror/throwable.h" 47 #include "runtime.h" 48 #include "scoped_thread_state_change-inl.h" 49 #include "thread.h" 50 #include "well_known_classes.h" 51 52 namespace art { 53 namespace { 54 55 using android::base::StringAppendF; 56 using android::base::StringPrintf; 57 58 /* 59 * =========================================================================== 60 * JNI function helpers 61 * =========================================================================== 62 */ 63 64 // Warn if a JNI critical is held for longer than 16ms. 65 static constexpr uint64_t kCriticalWarnTimeUs = MsToUs(16); 66 static_assert(kCriticalWarnTimeUs > 0, "No JNI critical warn time set"); 67 68 // True if primitives within specific ranges cause a fatal error, 69 // otherwise just warn. 70 static constexpr bool kBrokenPrimitivesAreFatal = kIsDebugBuild; 71 72 // Flags passed into ScopedCheck. 73 static constexpr uint16_t kFlag_Default = 0x0000; 74 75 // Calling while in critical is not allowed. 76 static constexpr uint16_t kFlag_CritBad = 0x0000; 77 // Calling while in critical is allowed. 78 static constexpr uint16_t kFlag_CritOkay = 0x0001; 79 // This is a critical "get". 80 static constexpr uint16_t kFlag_CritGet = 0x0002; 81 // This is a critical "release". 82 static constexpr uint16_t kFlag_CritRelease = 0x0003; 83 // Bit mask to get "crit" value. 84 static constexpr uint16_t kFlag_CritMask = 0x0003; 85 86 // Raised exceptions are allowed. 87 static constexpr uint16_t kFlag_ExcepOkay = 0x0004; 88 89 // Are we in a non-critical release function? 90 static constexpr uint16_t kFlag_Release = 0x0010; 91 // Are our UTF parameters nullable? 92 static constexpr uint16_t kFlag_NullableUtf = 0x0020; 93 94 // Part of the invocation interface (JavaVM*). 95 static constexpr uint16_t kFlag_Invocation = 0x0100; 96 97 // Add this to a JNI function's flags if you want to trace every call. 98 static constexpr uint16_t kFlag_ForceTrace = 0x8000; 99 100 class VarArgs; 101 /* 102 * Java primitive types: 103 * B - jbyte 104 * C - jchar 105 * D - jdouble 106 * F - jfloat 107 * I - jint 108 * J - jlong 109 * S - jshort 110 * Z - jboolean (shown as true and false) 111 * V - void 112 * 113 * Java reference types: 114 * L - jobject 115 * a - jarray 116 * c - jclass 117 * s - jstring 118 * t - jthrowable 119 * 120 * JNI types: 121 * b - jboolean (shown as JNI_TRUE and JNI_FALSE) 122 * f - jfieldID 123 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION) 124 * m - jmethodID 125 * p - void* 126 * r - jint (for release mode arguments) 127 * u - const char* (Modified UTF-8) 128 * z - jsize (for lengths; use i if negative values are okay) 129 * v - JavaVM* 130 * w - jobjectRefType 131 * E - JNIEnv* 132 * . - no argument; just print "..." (used for varargs JNI calls) 133 * 134 */ 135 union JniValueType { 136 jarray a; 137 jboolean b; 138 jclass c; 139 jfieldID f; 140 jint i; 141 jmethodID m; 142 const void* p; // Pointer. 143 jint r; // Release mode. 144 jstring s; 145 jthrowable t; 146 const char* u; // Modified UTF-8. 147 JavaVM* v; 148 jobjectRefType w; 149 jsize z; 150 jbyte B; 151 jchar C; 152 jdouble D; 153 JNIEnv* E; 154 jfloat F; 155 jint I; 156 jlong J; 157 jobject L; 158 jshort S; 159 const void* V; // void 160 jboolean Z; 161 const VarArgs* va; 162 }; 163 164 /* 165 * A structure containing all the information needed to validate varargs arguments. 166 * 167 * Note that actually getting the arguments from this structure mutates it so should only be done on 168 * owned copies. 169 */ 170 class VarArgs { 171 public: 172 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) { 173 va_copy(vargs_, var); 174 } 175 176 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {} 177 178 ~VarArgs() { 179 if (type_ == kTypeVaList) { 180 va_end(vargs_); 181 } 182 } 183 184 VarArgs(VarArgs&& other) noexcept { 185 m_ = other.m_; 186 cnt_ = other.cnt_; 187 type_ = other.type_; 188 if (other.type_ == kTypeVaList) { 189 va_copy(vargs_, other.vargs_); 190 } else { 191 ptr_ = other.ptr_; 192 } 193 } 194 195 // This method is const because we need to ensure that one only uses the GetValue method on an 196 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a 197 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when 198 // we want to use one we need to Clone() it. 199 VarArgs Clone() const { 200 if (type_ == kTypeVaList) { 201 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is 202 // messed up if the source argument is not the exact type 'va_list'. 203 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_); 204 } else { 205 return VarArgs(m_, cnt_, ptr_); 206 } 207 } 208 209 jmethodID GetMethodID() const { 210 return m_; 211 } 212 213 JniValueType GetValue(char fmt) { 214 JniValueType o; 215 if (type_ == kTypeVaList) { 216 switch (fmt) { 217 // Assign a full int for va_list values as this is what is done in reflection.cc. 218 // TODO(b/73656264): avoid undefined behavior. 219 case 'Z': FALLTHROUGH_INTENDED; 220 case 'B': FALLTHROUGH_INTENDED; 221 case 'C': FALLTHROUGH_INTENDED; 222 case 'S': FALLTHROUGH_INTENDED; 223 case 'I': o.I = va_arg(vargs_, jint); break; 224 case 'J': o.J = va_arg(vargs_, jlong); break; 225 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break; 226 case 'D': o.D = va_arg(vargs_, jdouble); break; 227 case 'L': o.L = va_arg(vargs_, jobject); break; 228 default: 229 LOG(FATAL) << "Illegal type format char " << fmt; 230 UNREACHABLE(); 231 } 232 } else { 233 CHECK(type_ == kTypePtr); 234 jvalue v = ptr_[cnt_]; 235 cnt_++; 236 switch (fmt) { 237 // Copy just the amount of the jvalue necessary, as done in 238 // reflection.cc, but extend to an int to be consistent with 239 // var args in CheckNonHeapValue. 240 // TODO(b/73656264): avoid undefined behavior. 241 case 'Z': o.I = v.z; break; 242 case 'B': o.I = v.b; break; 243 case 'C': o.I = v.c; break; 244 case 'S': o.I = v.s; break; 245 case 'I': o.I = v.i; break; 246 case 'J': o.J = v.j; break; 247 case 'F': o.F = v.f; break; 248 case 'D': o.D = v.d; break; 249 case 'L': o.L = v.l; break; 250 default: 251 LOG(FATAL) << "Illegal type format char " << fmt; 252 UNREACHABLE(); 253 } 254 } 255 return o; 256 } 257 258 private: 259 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) { 260 va_copy(vargs_, var); 261 } 262 263 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {} 264 265 enum VarArgsType { 266 kTypeVaList, 267 kTypePtr, 268 }; 269 270 jmethodID m_; 271 VarArgsType type_; 272 uint32_t cnt_; 273 union { 274 va_list vargs_; 275 const jvalue* ptr_; 276 }; 277 }; 278 279 // Check whether the current thread is attached. This is usually required 280 // to be the first check, as ScopedCheck needs a ScopedObjectAccess for 281 // checking heap values (and that will fail with unattached threads). 282 bool CheckAttachedThread(const char* function_name) { 283 Thread* self = Thread::Current(); 284 if (UNLIKELY(self == nullptr)) { 285 // Need to attach this thread for a proper abort to work. We prefer this 286 // to get reasonable stacks and environment, rather than relying on 287 // tombstoned. 288 JNIEnv* env; 289 Runtime::Current()->GetJavaVM()->AttachCurrentThread(&env, /* thr_args= */ nullptr); 290 291 std::string tmp = android::base::StringPrintf( 292 "a thread (tid %" PRId64 " is making JNI calls without being attached", 293 static_cast<int64_t>(GetTid())); 294 Runtime::Current()->GetJavaVM()->JniAbort(function_name, tmp.c_str()); 295 296 CHECK_NE(Runtime::Current()->GetJavaVM()->DetachCurrentThread(), JNI_ERR); 297 return false; 298 } 299 return true; 300 } 301 302 // Macro helpers for the above. 303 #define CHECK_ATTACHED_THREAD(function_name, fail_val) \ 304 do { \ 305 if (!CheckAttachedThread((function_name))) { \ 306 return fail_val; \ 307 } \ 308 } while (false) 309 #define CHECK_ATTACHED_THREAD_VOID(function_name) \ 310 do { \ 311 if (!CheckAttachedThread((function_name))) { \ 312 return; \ 313 } \ 314 } while (false) 315 316 class ScopedCheck { 317 public: 318 ScopedCheck(uint16_t flags, const char* functionName, bool has_method = true) 319 : function_name_(functionName), indent_(0), flags_(flags), has_method_(has_method) { 320 } 321 322 ~ScopedCheck() {} 323 324 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread" 325 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of 326 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some 327 // circumstances, but this is incorrect. 328 bool CheckClassName(const char* class_name) { 329 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) { 330 AbortF("illegal class name '%s'\n" 331 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')", 332 class_name); 333 return false; 334 } 335 return true; 336 } 337 338 /* 339 * Verify that this instance field ID is valid for this object. 340 * 341 * Assumes "jobj" has already been validated. 342 */ 343 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid) 344 REQUIRES_SHARED(Locks::mutator_lock_) { 345 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object); 346 if (o == nullptr) { 347 AbortF("field operation on NULL object: %p", java_object); 348 return false; 349 } 350 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) { 351 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 352 AbortF("field operation on invalid %s: %p", 353 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)), 354 java_object); 355 return false; 356 } 357 358 ArtField* f = CheckFieldID(fid); 359 if (f == nullptr) { 360 return false; 361 } 362 ObjPtr<mirror::Class> c = o->GetClass(); 363 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) { 364 AbortF("jfieldID %s not valid for an object of class %s", 365 f->PrettyField().c_str(), o->PrettyTypeOf().c_str()); 366 return false; 367 } 368 return true; 369 } 370 371 /* 372 * Verify that the pointer value is non-null. 373 */ 374 bool CheckNonNull(const void* ptr) { 375 if (UNLIKELY(ptr == nullptr)) { 376 AbortF("non-nullable argument was NULL"); 377 return false; 378 } 379 return true; 380 } 381 382 /* 383 * Verify that the method's return type matches the type of call. 384 * 'expectedType' will be "L" for all objects, including arrays. 385 */ 386 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc, 387 jmethodID mid, Primitive::Type type, InvokeType invoke) 388 REQUIRES_SHARED(Locks::mutator_lock_) { 389 ArtMethod* m = CheckMethodID(mid); 390 if (m == nullptr) { 391 return false; 392 } 393 if (type != Primitive::GetType(m->GetShorty()[0])) { 394 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str()); 395 return false; 396 } 397 bool is_static = (invoke == kStatic); 398 if (is_static != m->IsStatic()) { 399 if (is_static) { 400 AbortF("calling non-static method %s with %s", 401 m->PrettyMethod().c_str(), function_name_); 402 } else { 403 AbortF("calling static method %s with %s", 404 m->PrettyMethod().c_str(), function_name_); 405 } 406 return false; 407 } 408 if (invoke != kVirtual) { 409 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); 410 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { 411 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual", 412 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str()); 413 return false; 414 } 415 } 416 if (invoke != kStatic) { 417 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj); 418 if (o == nullptr) { 419 AbortF("can't call %s on null object", m->PrettyMethod().c_str()); 420 return false; 421 } else if (!o->InstanceOf(m->GetDeclaringClass())) { 422 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(), 423 o->PrettyTypeOf().c_str()); 424 return false; 425 } 426 } 427 return true; 428 } 429 430 /* 431 * Verify that this static field ID is valid for this class. 432 * 433 * Assumes "java_class" has already been validated. 434 */ 435 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid) 436 REQUIRES_SHARED(Locks::mutator_lock_) { 437 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class); 438 ArtField* f = CheckFieldID(fid); 439 if (f == nullptr) { 440 return false; 441 } 442 if (!f->GetDeclaringClass()->IsAssignableFrom(c)) { 443 AbortF("static jfieldID %p not valid for class %s", fid, 444 mirror::Class::PrettyClass(c).c_str()); 445 return false; 446 } 447 return true; 448 } 449 450 /* 451 * Verify that "mid" is appropriate for "java_class". 452 * 453 * A mismatch isn't dangerous, because the jmethodID defines the class. In 454 * fact, java_class is unused in the implementation. It's best if we don't 455 * allow bad code in the system though. 456 * 457 * Instances of "java_class" must be instances of the method's declaring class. 458 */ 459 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid) 460 REQUIRES_SHARED(Locks::mutator_lock_) { 461 ArtMethod* m = CheckMethodID(mid); 462 if (m == nullptr) { 463 return false; 464 } 465 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class); 466 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { 467 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(), 468 mirror::Class::PrettyClass(c).c_str()); 469 return false; 470 } 471 return true; 472 } 473 474 /* 475 * Verify that "mid" is appropriate for "jobj". 476 * 477 * Make sure the object is an instance of the method's declaring class. 478 * (Note the mid might point to a declaration in an interface; this 479 * will be handled automatically by the instanceof check.) 480 */ 481 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid) 482 REQUIRES_SHARED(Locks::mutator_lock_) { 483 ArtMethod* m = CheckMethodID(mid); 484 if (m == nullptr) { 485 return false; 486 } 487 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object); 488 if (o == nullptr) { 489 AbortF("can't call %s on null object", m->PrettyMethod().c_str()); 490 return false; 491 } else if (!o->InstanceOf(m->GetDeclaringClass())) { 492 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(), 493 o->PrettyTypeOf().c_str()); 494 return false; 495 } 496 return true; 497 } 498 499 /** 500 * The format string is a sequence of the following characters, 501 * and must be followed by arguments of the corresponding types 502 * in the same order. 503 * 504 * Java primitive types: 505 * B - jbyte 506 * C - jchar 507 * D - jdouble 508 * F - jfloat 509 * I - jint 510 * J - jlong 511 * S - jshort 512 * Z - jboolean (shown as true and false) 513 * V - void 514 * 515 * Java reference types: 516 * L - jobject 517 * a - jarray 518 * c - jclass 519 * s - jstring 520 * 521 * JNI types: 522 * b - jboolean (shown as JNI_TRUE and JNI_FALSE) 523 * f - jfieldID 524 * m - jmethodID 525 * p - void* 526 * r - jint (for release mode arguments) 527 * u - const char* (Modified UTF-8) 528 * z - jsize (for lengths; use i if negative values are okay) 529 * v - JavaVM* 530 * E - JNIEnv* 531 * . - VarArgs* for Jni calls with variable length arguments 532 * 533 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable. 534 */ 535 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args) 536 REQUIRES_SHARED(Locks::mutator_lock_) { 537 ArtMethod* traceMethod = nullptr; 538 if (has_method_ && soa.Vm()->IsTracingEnabled()) { 539 // We need to guard some of the invocation interface's calls: a bad caller might 540 // use DetachCurrentThread or GetEnv on a thread that's not yet attached. 541 Thread* self = Thread::Current(); 542 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) { 543 traceMethod = self->GetCurrentMethod(nullptr); 544 } 545 } 546 547 if (((flags_ & kFlag_ForceTrace) != 0) || 548 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) { 549 std::string msg; 550 for (size_t i = 0; fmt[i] != '\0'; ++i) { 551 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg); 552 if (fmt[i + 1] != '\0') { 553 StringAppendF(&msg, ", "); 554 } 555 } 556 557 if ((flags_ & kFlag_ForceTrace) != 0) { 558 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")"; 559 } else if (entry) { 560 if (has_method_) { 561 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false)); 562 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")"; 563 indent_ = methodName.size() + 1; 564 } else { 565 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")"; 566 indent_ = 0; 567 } 568 } else { 569 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str()); 570 } 571 } 572 573 // We always do the thorough checks on entry, and never on exit... 574 if (entry) { 575 for (size_t i = 0; fmt[i] != '\0'; ++i) { 576 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) { 577 return false; 578 } 579 } 580 } 581 return true; 582 } 583 584 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) { 585 bool should_trace = (flags_ & kFlag_ForceTrace) != 0; 586 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) { 587 // We need to guard some of the invocation interface's calls: a bad caller might 588 // use DetachCurrentThread or GetEnv on a thread that's not yet attached. 589 Thread* self = Thread::Current(); 590 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) { 591 ScopedObjectAccess soa(self); 592 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr); 593 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod)); 594 } 595 } 596 if (should_trace) { 597 std::string msg; 598 for (size_t i = 0; fmt[i] != '\0'; ++i) { 599 TraceNonHeapValue(fmt[i], args[i], &msg); 600 if (fmt[i + 1] != '\0') { 601 StringAppendF(&msg, ", "); 602 } 603 } 604 605 if ((flags_ & kFlag_ForceTrace) != 0) { 606 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")"; 607 } else if (entry) { 608 if (has_method_) { 609 Thread* self = Thread::Current(); 610 ScopedObjectAccess soa(self); 611 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr); 612 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false)); 613 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")"; 614 indent_ = methodName.size() + 1; 615 } else { 616 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")"; 617 indent_ = 0; 618 } 619 } else { 620 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str()); 621 } 622 } 623 624 // We always do the thorough checks on entry, and never on exit... 625 if (entry) { 626 for (size_t i = 0; fmt[i] != '\0'; ++i) { 627 if (!CheckNonHeapValue(fmt[i], args[i])) { 628 return false; 629 } 630 } 631 } 632 return true; 633 } 634 635 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod) 636 REQUIRES_SHARED(Locks::mutator_lock_) { 637 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod); 638 if (method == nullptr) { 639 AbortF("expected non-null method"); 640 return false; 641 } 642 ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = 643 Runtime::Current()->GetClassLinker()->GetClassRoots(); 644 ObjPtr<mirror::Class> c = method->GetClass(); 645 if (c != GetClassRoot<mirror::Method>(class_roots) && 646 c != GetClassRoot<mirror::Constructor>(class_roots)) { 647 AbortF("expected java.lang.reflect.Method or " 648 "java.lang.reflect.Constructor but got object of type %s: %p", 649 method->PrettyTypeOf().c_str(), jmethod); 650 return false; 651 } 652 return true; 653 } 654 655 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) { 656 ArtMethod* method = jni::DecodeArtMethod(mid); 657 if (method == nullptr) { 658 AbortF("expected non-null constructor"); 659 return false; 660 } 661 if (!method->IsConstructor() || method->IsStatic()) { 662 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid); 663 return false; 664 } 665 return true; 666 } 667 668 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield) 669 REQUIRES_SHARED(Locks::mutator_lock_) { 670 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield); 671 if (field == nullptr) { 672 AbortF("expected non-null java.lang.reflect.Field"); 673 return false; 674 } 675 ObjPtr<mirror::Class> c = field->GetClass(); 676 if (GetClassRoot<mirror::Field>() != c) { 677 AbortF("expected java.lang.reflect.Field but got object of type %s: %p", 678 field->PrettyTypeOf().c_str(), jfield); 679 return false; 680 } 681 return true; 682 } 683 684 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj) 685 REQUIRES_SHARED(Locks::mutator_lock_) { 686 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj); 687 if (!obj->GetClass()->IsThrowableClass()) { 688 AbortF("expected java.lang.Throwable but got object of type " 689 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr()); 690 return false; 691 } 692 return true; 693 } 694 695 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc) 696 REQUIRES_SHARED(Locks::mutator_lock_) { 697 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); 698 if (!c->IsThrowableClass()) { 699 AbortF("expected java.lang.Throwable class but got object of " 700 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr()); 701 return false; 702 } 703 return true; 704 } 705 706 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) { 707 IndirectRefKind found_kind; 708 if (expected_kind == kLocal) { 709 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj); 710 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) { 711 found_kind = kLocal; 712 } 713 } else { 714 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj); 715 } 716 if (obj != nullptr && found_kind != expected_kind) { 717 AbortF("expected reference of kind %s but found %s: %p", 718 GetIndirectRefKindString(expected_kind), 719 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)), 720 obj); 721 return false; 722 } 723 return true; 724 } 725 726 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc) 727 REQUIRES_SHARED(Locks::mutator_lock_) { 728 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); 729 if (!c->IsInstantiableNonArray()) { 730 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr()); 731 return false; 732 } 733 return true; 734 } 735 736 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type) 737 REQUIRES_SHARED(Locks::mutator_lock_) { 738 if (!CheckArray(soa, array)) { 739 return false; 740 } 741 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array); 742 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) { 743 AbortF("incompatible array type %s expected %s[]: %p", 744 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array); 745 return false; 746 } 747 return true; 748 } 749 750 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static, 751 Primitive::Type type) 752 REQUIRES_SHARED(Locks::mutator_lock_) { 753 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) { 754 return false; 755 } 756 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) { 757 return false; 758 } 759 ArtField* field = jni::DecodeArtField(fid); 760 DCHECK(field != nullptr); // Already checked by Check. 761 if (is_static != field->IsStatic()) { 762 AbortF("attempt to access %s field %s: %p", 763 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid); 764 return false; 765 } 766 if (type != field->GetTypeAsPrimitiveType()) { 767 AbortF("attempt to access field %s of type %s with the wrong type %s: %p", 768 field->PrettyField().c_str(), 769 PrettyDescriptor(field->GetTypeDescriptor()).c_str(), 770 PrettyDescriptor(type).c_str(), fid); 771 return false; 772 } 773 if (is_static) { 774 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj); 775 if (o == nullptr || !o->IsClass()) { 776 AbortF("attempt to access static field %s with a class argument of type %s: %p", 777 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid); 778 return false; 779 } 780 ObjPtr<mirror::Class> c = o->AsClass(); 781 if (!field->GetDeclaringClass()->IsAssignableFrom(c)) { 782 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p", 783 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid); 784 return false; 785 } 786 } else { 787 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj); 788 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) { 789 AbortF("attempt to access field %s from an object argument of type %s: %p", 790 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid); 791 return false; 792 } 793 } 794 return true; 795 } 796 797 private: 798 enum InstanceKind { 799 kClass, 800 kDirectByteBuffer, 801 kObject, 802 kString, 803 kThrowable, 804 }; 805 806 /* 807 * Verify that "jobj" is a valid non-null object reference, and points to 808 * an instance of expectedClass. 809 * 810 * Because we're looking at an object on the GC heap, we have to switch 811 * to "running" mode before doing the checks. 812 */ 813 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok) 814 REQUIRES_SHARED(Locks::mutator_lock_) { 815 const char* what = nullptr; 816 switch (kind) { 817 case kClass: 818 what = "jclass"; 819 break; 820 case kDirectByteBuffer: 821 what = "direct ByteBuffer"; 822 break; 823 case kObject: 824 what = "jobject"; 825 break; 826 case kString: 827 what = "jstring"; 828 break; 829 case kThrowable: 830 what = "jthrowable"; 831 break; 832 default: 833 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind); 834 } 835 836 if (java_object == nullptr) { 837 if (null_ok) { 838 return true; 839 } else { 840 AbortF("%s received NULL %s", function_name_, what); 841 return false; 842 } 843 } 844 845 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object); 846 if (obj == nullptr) { 847 // Either java_object is invalid or is a cleared weak. 848 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object); 849 bool okay; 850 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) { 851 okay = false; 852 } else { 853 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref); 854 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj); 855 } 856 if (!okay) { 857 AbortF("%s is an invalid %s: %p (%p)", 858 what, 859 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)), 860 java_object, 861 obj.Ptr()); 862 return false; 863 } 864 } 865 866 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) { 867 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 868 AbortF("%s is an invalid %s: %p (%p)", 869 what, 870 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)), 871 java_object, 872 obj.Ptr()); 873 return false; 874 } 875 876 bool okay = true; 877 switch (kind) { 878 case kClass: 879 okay = obj->IsClass(); 880 break; 881 case kDirectByteBuffer: 882 UNIMPLEMENTED(FATAL); 883 UNREACHABLE(); 884 case kString: 885 okay = obj->GetClass()->IsStringClass(); 886 break; 887 case kThrowable: 888 okay = obj->GetClass()->IsThrowableClass(); 889 break; 890 case kObject: 891 break; 892 } 893 if (!okay) { 894 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str()); 895 return false; 896 } 897 898 return true; 899 } 900 901 /* 902 * Verify that the "mode" argument passed to a primitive array Release 903 * function is one of the valid values. 904 */ 905 bool CheckReleaseMode(jint mode) { 906 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) { 907 AbortF("unknown value for release mode: %d", mode); 908 return false; 909 } 910 return true; 911 } 912 913 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg) 914 REQUIRES_SHARED(Locks::mutator_lock_) { 915 switch (fmt) { 916 case 'a': // jarray 917 return CheckArray(soa, arg.a); 918 case 'c': // jclass 919 return CheckInstance(soa, kClass, arg.c, false); 920 case 'f': // jfieldID 921 return CheckFieldID(arg.f) != nullptr; 922 case 'm': // jmethodID 923 return CheckMethodID(arg.m) != nullptr; 924 case 'r': // release int 925 return CheckReleaseMode(arg.r); 926 case 's': // jstring 927 return CheckInstance(soa, kString, arg.s, false); 928 case 't': // jthrowable 929 return CheckInstance(soa, kThrowable, arg.t, false); 930 case 'E': // JNIEnv* 931 return CheckThread(arg.E); 932 case 'L': // jobject 933 return CheckInstance(soa, kObject, arg.L, true); 934 case '.': // A VarArgs list 935 return CheckVarArgs(soa, arg.va); 936 default: 937 return CheckNonHeapValue(fmt, arg); 938 } 939 } 940 941 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p) 942 REQUIRES_SHARED(Locks::mutator_lock_) { 943 CHECK(args_p != nullptr); 944 VarArgs args(args_p->Clone()); 945 ArtMethod* m = CheckMethodID(args.GetMethodID()); 946 if (m == nullptr) { 947 return false; 948 } 949 uint32_t len = 0; 950 const char* shorty = m->GetShorty(&len); 951 // Skip the return type 952 CHECK_GE(len, 1u); 953 len--; 954 shorty++; 955 for (uint32_t i = 0; i < len; i++) { 956 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) { 957 return false; 958 } 959 } 960 return true; 961 } 962 963 bool CheckNonHeapValue(char fmt, JniValueType arg) { 964 switch (fmt) { 965 case 'p': // TODO: pointer - null or readable? 966 case 'v': // JavaVM* 967 case 'D': // jdouble 968 case 'F': // jfloat 969 case 'J': // jlong 970 case 'I': // jint 971 break; // Ignored. 972 case 'b': // jboolean, why two? Fall-through. 973 case 'Z': 974 return CheckBoolean(arg.I); 975 case 'B': // jbyte 976 return CheckByte(arg.I); 977 case 'C': // jchar 978 return CheckChar(arg.I); 979 case 'S': // jshort 980 return CheckShort(arg.I); 981 case 'u': // utf8 982 if ((flags_ & kFlag_Release) != 0) { 983 return CheckNonNull(arg.u); 984 } else { 985 bool nullable = ((flags_ & kFlag_NullableUtf) != 0); 986 return CheckUtfString(arg.u, nullable); 987 } 988 case 'w': // jobjectRefType 989 switch (arg.w) { 990 case JNIInvalidRefType: 991 case JNILocalRefType: 992 case JNIGlobalRefType: 993 case JNIWeakGlobalRefType: 994 break; 995 default: 996 AbortF("Unknown reference type"); 997 return false; 998 } 999 break; 1000 case 'z': // jsize 1001 return CheckLengthPositive(arg.z); 1002 default: 1003 AbortF("unknown format specifier: '%c'", fmt); 1004 return false; 1005 } 1006 return true; 1007 } 1008 1009 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg, 1010 std::string* msg) 1011 REQUIRES_SHARED(Locks::mutator_lock_) { 1012 switch (fmt) { 1013 case 'L': // jobject fall-through. 1014 case 'a': // jarray fall-through. 1015 case 's': // jstring fall-through. 1016 case 't': // jthrowable fall-through. 1017 if (arg.L == nullptr) { 1018 *msg += "NULL"; 1019 } else { 1020 StringAppendF(msg, "%p", arg.L); 1021 } 1022 break; 1023 case 'c': { // jclass 1024 jclass jc = arg.c; 1025 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); 1026 if (c == nullptr) { 1027 *msg += "NULL"; 1028 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) { 1029 StringAppendF(msg, "INVALID POINTER:%p", jc); 1030 } else if (!c->IsClass()) { 1031 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf(); 1032 } else { 1033 *msg += c->PrettyClass(); 1034 if (!entry) { 1035 StringAppendF(msg, " (%p)", jc); 1036 } 1037 } 1038 break; 1039 } 1040 case 'f': { // jfieldID 1041 jfieldID fid = arg.f; 1042 ArtField* f = jni::DecodeArtField(fid); 1043 *msg += ArtField::PrettyField(f); 1044 if (!entry) { 1045 StringAppendF(msg, " (%p)", fid); 1046 } 1047 break; 1048 } 1049 case 'm': { // jmethodID 1050 jmethodID mid = arg.m; 1051 ArtMethod* m = jni::DecodeArtMethod(mid); 1052 *msg += ArtMethod::PrettyMethod(m); 1053 if (!entry) { 1054 StringAppendF(msg, " (%p)", mid); 1055 } 1056 break; 1057 } 1058 case '.': { 1059 const VarArgs* va = arg.va; 1060 VarArgs args(va->Clone()); 1061 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID()); 1062 uint32_t len; 1063 const char* shorty = m->GetShorty(&len); 1064 CHECK_GE(len, 1u); 1065 // Skip past return value. 1066 len--; 1067 shorty++; 1068 // Remove the previous ', ' from the message. 1069 msg->erase(msg->length() - 2); 1070 for (uint32_t i = 0; i < len; i++) { 1071 *msg += ", "; 1072 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg); 1073 } 1074 break; 1075 } 1076 default: 1077 TraceNonHeapValue(fmt, arg, msg); 1078 break; 1079 } 1080 } 1081 1082 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) { 1083 switch (fmt) { 1084 case 'B': // jbyte 1085 if (arg.B >= 0 && arg.B < 10) { 1086 StringAppendF(msg, "%d", arg.B); 1087 } else { 1088 StringAppendF(msg, "%#x (%d)", arg.B, arg.B); 1089 } 1090 break; 1091 case 'C': // jchar 1092 if (arg.C < 0x7f && arg.C >= ' ') { 1093 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C); 1094 } else { 1095 StringAppendF(msg, "U+%x", arg.C); 1096 } 1097 break; 1098 case 'F': // jfloat 1099 StringAppendF(msg, "%g", arg.F); 1100 break; 1101 case 'D': // jdouble 1102 StringAppendF(msg, "%g", arg.D); 1103 break; 1104 case 'S': // jshort 1105 StringAppendF(msg, "%d", arg.S); 1106 break; 1107 case 'i': // jint - fall-through. 1108 case 'I': // jint 1109 StringAppendF(msg, "%d", arg.I); 1110 break; 1111 case 'J': // jlong 1112 StringAppendF(msg, "%" PRId64, arg.J); 1113 break; 1114 case 'Z': // jboolean 1115 case 'b': // jboolean (JNI-style) 1116 *msg += arg.b == JNI_TRUE ? "true" : "false"; 1117 break; 1118 case 'V': // void 1119 DCHECK(arg.V == nullptr); 1120 *msg += "void"; 1121 break; 1122 case 'v': // JavaVM* 1123 StringAppendF(msg, "(JavaVM*)%p", arg.v); 1124 break; 1125 case 'E': 1126 StringAppendF(msg, "(JNIEnv*)%p", arg.E); 1127 break; 1128 case 'z': // non-negative jsize 1129 // You might expect jsize to be size_t, but it's not; it's the same as jint. 1130 // We only treat this specially so we can do the non-negative check. 1131 // TODO: maybe this wasn't worth it? 1132 StringAppendF(msg, "%d", arg.z); 1133 break; 1134 case 'p': // void* ("pointer") 1135 if (arg.p == nullptr) { 1136 *msg += "NULL"; 1137 } else { 1138 StringAppendF(msg, "(void*) %p", arg.p); 1139 } 1140 break; 1141 case 'r': { // jint (release mode) 1142 jint releaseMode = arg.r; 1143 if (releaseMode == 0) { 1144 *msg += "0"; 1145 } else if (releaseMode == JNI_ABORT) { 1146 *msg += "JNI_ABORT"; 1147 } else if (releaseMode == JNI_COMMIT) { 1148 *msg += "JNI_COMMIT"; 1149 } else { 1150 StringAppendF(msg, "invalid release mode %d", releaseMode); 1151 } 1152 break; 1153 } 1154 case 'u': // const char* (Modified UTF-8) 1155 if (arg.u == nullptr) { 1156 *msg += "NULL"; 1157 } else { 1158 StringAppendF(msg, "\"%s\"", arg.u); 1159 } 1160 break; 1161 case 'w': // jobjectRefType 1162 switch (arg.w) { 1163 case JNIInvalidRefType: 1164 *msg += "invalid reference type"; 1165 break; 1166 case JNILocalRefType: 1167 *msg += "local ref type"; 1168 break; 1169 case JNIGlobalRefType: 1170 *msg += "global ref type"; 1171 break; 1172 case JNIWeakGlobalRefType: 1173 *msg += "weak global ref type"; 1174 break; 1175 default: 1176 *msg += "unknown ref type"; 1177 break; 1178 } 1179 break; 1180 default: 1181 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'"; 1182 } 1183 } 1184 /* 1185 * Verify that "array" is non-null and points to an Array object. 1186 * 1187 * Since we're dealing with objects, switch to "running" mode. 1188 */ 1189 bool CheckArray(ScopedObjectAccess& soa, jarray java_array) 1190 REQUIRES_SHARED(Locks::mutator_lock_) { 1191 if (UNLIKELY(java_array == nullptr)) { 1192 AbortF("jarray was NULL"); 1193 return false; 1194 } 1195 1196 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array); 1197 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) { 1198 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 1199 AbortF("jarray is an invalid %s: %p (%p)", 1200 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)), 1201 java_array, 1202 a.Ptr()); 1203 return false; 1204 } else if (!a->IsArrayInstance()) { 1205 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str()); 1206 return false; 1207 } 1208 return true; 1209 } 1210 1211 bool CheckBoolean(jint z) { 1212 if (z != JNI_TRUE && z != JNI_FALSE) { 1213 // Note, broken booleans are always fatal. 1214 AbortF("unexpected jboolean value: %d", z); 1215 return false; 1216 } 1217 return true; 1218 } 1219 1220 bool CheckByte(jint b) { 1221 if (b < std::numeric_limits<jbyte>::min() || 1222 b > std::numeric_limits<jbyte>::max()) { 1223 if (kBrokenPrimitivesAreFatal) { 1224 AbortF("unexpected jbyte value: %d", b); 1225 return false; 1226 } else { 1227 LOG(WARNING) << "Unexpected jbyte value: " << b; 1228 } 1229 } 1230 return true; 1231 } 1232 1233 bool CheckShort(jint s) { 1234 if (s < std::numeric_limits<jshort>::min() || 1235 s > std::numeric_limits<jshort>::max()) { 1236 if (kBrokenPrimitivesAreFatal) { 1237 AbortF("unexpected jshort value: %d", s); 1238 return false; 1239 } else { 1240 LOG(WARNING) << "Unexpected jshort value: " << s; 1241 } 1242 } 1243 return true; 1244 } 1245 1246 bool CheckChar(jint c) { 1247 if (c < std::numeric_limits<jchar>::min() || 1248 c > std::numeric_limits<jchar>::max()) { 1249 if (kBrokenPrimitivesAreFatal) { 1250 AbortF("unexpected jchar value: %d", c); 1251 return false; 1252 } else { 1253 LOG(WARNING) << "Unexpected jchar value: " << c; 1254 } 1255 } 1256 return true; 1257 } 1258 1259 bool CheckLengthPositive(jsize length) { 1260 if (length < 0) { 1261 AbortF("negative jsize: %d", length); 1262 return false; 1263 } 1264 return true; 1265 } 1266 1267 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) { 1268 if (fid == nullptr) { 1269 AbortF("jfieldID was NULL"); 1270 return nullptr; 1271 } 1272 ArtField* f = jni::DecodeArtField(fid); 1273 // TODO: Better check here. 1274 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) { 1275 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 1276 AbortF("invalid jfieldID: %p", fid); 1277 return nullptr; 1278 } 1279 return f; 1280 } 1281 1282 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) { 1283 if (mid == nullptr) { 1284 AbortF("jmethodID was NULL"); 1285 return nullptr; 1286 } 1287 ArtMethod* m = jni::DecodeArtMethod(mid); 1288 // TODO: Better check here. 1289 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass().Ptr())) { 1290 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 1291 AbortF("invalid jmethodID: %p", mid); 1292 return nullptr; 1293 } 1294 return m; 1295 } 1296 1297 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) { 1298 Thread* self = Thread::Current(); 1299 CHECK(self != nullptr); 1300 1301 // Get the current thread's JNIEnv by going through our TLS pointer. 1302 JNIEnvExt* threadEnv = self->GetJniEnv(); 1303 1304 // Verify that the current thread is (a) attached and (b) associated with 1305 // this particular instance of JNIEnv. 1306 if (env != threadEnv) { 1307 // Get the thread owning the JNIEnv that's being used. 1308 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf(); 1309 AbortF("thread %s using JNIEnv* from thread %s", 1310 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str()); 1311 return false; 1312 } 1313 1314 // Verify that, if this thread previously made a critical "get" call, we 1315 // do the corresponding "release" call before we try anything else. 1316 switch (flags_ & kFlag_CritMask) { 1317 case kFlag_CritOkay: // okay to call this method 1318 break; 1319 case kFlag_CritBad: // not okay to call 1320 if (threadEnv->GetCritical() > 0) { 1321 AbortF("thread %s using JNI after critical get", 1322 ToStr<Thread>(*self).c_str()); 1323 return false; 1324 } 1325 break; 1326 case kFlag_CritGet: // this is a "get" call 1327 // Don't check here; we allow nested gets. 1328 if (threadEnv->GetCritical() == 0) { 1329 threadEnv->SetCriticalStartUs(self->GetCpuMicroTime()); 1330 } 1331 threadEnv->SetCritical(threadEnv->GetCritical() + 1); 1332 break; 1333 case kFlag_CritRelease: // this is a "release" call 1334 if (threadEnv->GetCritical() == 0) { 1335 AbortF("thread %s called too many critical releases", 1336 ToStr<Thread>(*self).c_str()); 1337 return false; 1338 } else if (threadEnv->GetCritical() == 1) { 1339 // Leaving the critical region, possibly warn about long critical regions. 1340 uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs(); 1341 if (critical_duration_us > kCriticalWarnTimeUs) { 1342 LOG(WARNING) << "JNI critical lock held for " 1343 << PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self; 1344 } 1345 } 1346 threadEnv->SetCritical(threadEnv->GetCritical() - 1); 1347 break; 1348 default: 1349 LOG(FATAL) << "Bad flags (internal error): " << flags_; 1350 } 1351 1352 // Verify that, if an exception has been raised, the native code doesn't 1353 // make any JNI calls other than the Exception* methods. 1354 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) { 1355 mirror::Throwable* exception = self->GetException(); 1356 AbortF("JNI %s called with pending exception %s", 1357 function_name_, 1358 exception->Dump().c_str()); 1359 return false; 1360 } 1361 return true; 1362 } 1363 1364 // Verifies that "bytes" points to valid Modified UTF-8 data. 1365 bool CheckUtfString(const char* bytes, bool nullable) { 1366 if (bytes == nullptr) { 1367 if (!nullable) { 1368 AbortF("non-nullable const char* was NULL"); 1369 return false; 1370 } 1371 return true; 1372 } 1373 1374 const char* errorKind = nullptr; 1375 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind); 1376 if (errorKind != nullptr) { 1377 // This is an expensive loop that will resize often, but this isn't supposed to hit in 1378 // practice anyways. 1379 std::ostringstream oss; 1380 oss << std::hex; 1381 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes); 1382 while (*tmp != 0) { 1383 if (tmp == utf8) { 1384 oss << "<"; 1385 } 1386 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp); 1387 if (tmp == utf8) { 1388 oss << '>'; 1389 } 1390 tmp++; 1391 if (*tmp != 0) { 1392 oss << ' '; 1393 } 1394 } 1395 1396 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n" 1397 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str()); 1398 return false; 1399 } 1400 return true; 1401 } 1402 1403 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF 1404 // sequences in place of encoded surrogate pairs. 1405 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) { 1406 while (*bytes != '\0') { 1407 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1408 // Switch on the high four bits. 1409 switch (*utf8 >> 4) { 1410 case 0x00: 1411 case 0x01: 1412 case 0x02: 1413 case 0x03: 1414 case 0x04: 1415 case 0x05: 1416 case 0x06: 1417 case 0x07: 1418 // Bit pattern 0xxx. No need for any extra bytes. 1419 break; 1420 case 0x08: 1421 case 0x09: 1422 case 0x0a: 1423 case 0x0b: 1424 // Bit patterns 10xx, which are illegal start bytes. 1425 *errorKind = "start"; 1426 return utf8; 1427 case 0x0f: 1428 // Bit pattern 1111, which might be the start of a 4 byte sequence. 1429 if ((*utf8 & 0x08) == 0) { 1430 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence. 1431 // We consume one continuation byte here, and fall through to consume two more. 1432 utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1433 if ((*utf8 & 0xc0) != 0x80) { 1434 *errorKind = "continuation"; 1435 return utf8; 1436 } 1437 } else { 1438 *errorKind = "start"; 1439 return utf8; 1440 } 1441 1442 // Fall through to the cases below to consume two more continuation bytes. 1443 FALLTHROUGH_INTENDED; 1444 case 0x0e: 1445 // Bit pattern 1110, so there are two additional bytes. 1446 utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1447 if ((*utf8 & 0xc0) != 0x80) { 1448 *errorKind = "continuation"; 1449 return utf8; 1450 } 1451 1452 // Fall through to consume one more continuation byte. 1453 FALLTHROUGH_INTENDED; 1454 case 0x0c: 1455 case 0x0d: 1456 // Bit pattern 110x, so there is one additional byte. 1457 utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1458 if ((*utf8 & 0xc0) != 0x80) { 1459 *errorKind = "continuation"; 1460 return utf8; 1461 } 1462 break; 1463 } 1464 } 1465 return nullptr; 1466 } 1467 1468 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) { 1469 va_list args; 1470 va_start(args, fmt); 1471 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args); 1472 va_end(args); 1473 } 1474 1475 // The name of the JNI function being checked. 1476 const char* const function_name_; 1477 1478 int indent_; 1479 1480 const uint16_t flags_; 1481 1482 const bool has_method_; 1483 1484 DISALLOW_COPY_AND_ASSIGN(ScopedCheck); 1485 }; 1486 1487 /* 1488 * =========================================================================== 1489 * Guarded arrays 1490 * =========================================================================== 1491 */ 1492 1493 /* this gets tucked in at the start of the buffer; struct size must be even */ 1494 class GuardedCopy { 1495 public: 1496 /* 1497 * Create an over-sized buffer to hold the contents of "buf". Copy it in, 1498 * filling in the area around it with guard data. 1499 */ 1500 static void* Create(void* original_buf, size_t len, bool mod_okay) { 1501 const size_t new_len = LengthIncludingRedZones(len); 1502 uint8_t* const new_buf = DebugAlloc(new_len); 1503 1504 // If modification is not expected, grab a checksum. 1505 uLong adler = 0; 1506 if (!mod_okay) { 1507 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len); 1508 } 1509 1510 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler); 1511 1512 // Fill begin region with canary pattern. 1513 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy); 1514 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) { 1515 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j]; 1516 if (kCanary[j] == '\0') { 1517 j = 0; 1518 } else { 1519 j++; 1520 } 1521 } 1522 1523 // Copy the data in; note "len" could be zero. 1524 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len); 1525 1526 // Fill end region with canary pattern. 1527 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) { 1528 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j]; 1529 if (kCanary[j] == '\0') { 1530 j = 0; 1531 } else { 1532 j++; 1533 } 1534 } 1535 1536 return const_cast<uint8_t*>(copy->BufferWithinRedZones()); 1537 } 1538 1539 /* 1540 * Create a guarded copy of a primitive array. Modifications to the copied 1541 * data are allowed. Returns a pointer to the copied data. 1542 */ 1543 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy, 1544 void* original_ptr) { 1545 ScopedObjectAccess soa(env); 1546 1547 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array); 1548 size_t component_size = a->GetClass()->GetComponentSize(); 1549 size_t byte_count = a->GetLength() * component_size; 1550 void* result = Create(original_ptr, byte_count, true); 1551 if (is_copy != nullptr) { 1552 *is_copy = JNI_TRUE; 1553 } 1554 return result; 1555 } 1556 1557 /* 1558 * Perform the array "release" operation, which may or may not copy data 1559 * back into the managed heap, and may or may not release the underlying storage. 1560 */ 1561 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, 1562 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf, 1563 int mode) { 1564 ScopedObjectAccess soa(env); 1565 if (!GuardedCopy::Check(function_name, embedded_buf, true)) { 1566 return nullptr; 1567 } 1568 GuardedCopy* const copy = FromEmbedded(embedded_buf); 1569 void* original_ptr = copy->original_ptr_; 1570 if (mode != JNI_ABORT) { 1571 memcpy(original_ptr, embedded_buf, copy->original_length_); 1572 } 1573 if (mode != JNI_COMMIT) { 1574 Destroy(embedded_buf); 1575 } 1576 return original_ptr; 1577 } 1578 1579 1580 /* 1581 * Free up the guard buffer, scrub it, and return the original pointer. 1582 */ 1583 static void* Destroy(void* embedded_buf) { 1584 GuardedCopy* copy = FromEmbedded(embedded_buf); 1585 void* original_ptr = const_cast<void*>(copy->original_ptr_); 1586 size_t len = LengthIncludingRedZones(copy->original_length_); 1587 DebugFree(copy, len); 1588 return original_ptr; 1589 } 1590 1591 /* 1592 * Verify the guard area and, if "modOkay" is false, that the data itself 1593 * has not been altered. 1594 * 1595 * The caller has already checked that "dataBuf" is non-null. 1596 */ 1597 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) { 1598 const GuardedCopy* copy = FromEmbedded(embedded_buf); 1599 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name); 1600 } 1601 1602 private: 1603 GuardedCopy(void* original_buf, size_t len, uLong adler) : 1604 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) { 1605 } 1606 1607 static uint8_t* DebugAlloc(size_t len) { 1608 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); 1609 if (result == MAP_FAILED) { 1610 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed"; 1611 } 1612 return reinterpret_cast<uint8_t*>(result); 1613 } 1614 1615 static void DebugFree(void* buf, size_t len) { 1616 if (munmap(buf, len) != 0) { 1617 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed"; 1618 } 1619 } 1620 1621 static size_t LengthIncludingRedZones(size_t len) { 1622 return len + kRedZoneSize; 1623 } 1624 1625 // Get the GuardedCopy from the interior pointer. 1626 static GuardedCopy* FromEmbedded(void* embedded_buf) { 1627 return reinterpret_cast<GuardedCopy*>( 1628 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2)); 1629 } 1630 1631 static const GuardedCopy* FromEmbedded(const void* embedded_buf) { 1632 return reinterpret_cast<const GuardedCopy*>( 1633 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2)); 1634 } 1635 1636 static void AbortF(const char* jni_function_name, const char* fmt, ...) { 1637 va_list args; 1638 va_start(args, fmt); 1639 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args); 1640 va_end(args); 1641 } 1642 1643 bool CheckHeader(const char* function_name, bool mod_okay) const { 1644 static const uint32_t kMagicCmp = kGuardMagic; 1645 1646 // Before we do anything with "pExtra", check the magic number. We 1647 // do the check with memcmp rather than "==" in case the pointer is 1648 // unaligned. If it points to completely bogus memory we're going 1649 // to crash, but there's no easy way around that. 1650 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) { 1651 uint8_t buf[4]; 1652 memcpy(buf, &magic_, 4); 1653 AbortF(function_name, 1654 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?", 1655 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian. 1656 return false; 1657 } 1658 1659 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we 1660 // told the client that we made a copy, there's no reason they can't alter the buffer. 1661 if (!mod_okay) { 1662 uLong computed_adler = 1663 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_); 1664 if (computed_adler != adler_) { 1665 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p", 1666 computed_adler, adler_, this); 1667 return false; 1668 } 1669 } 1670 return true; 1671 } 1672 1673 bool CheckRedZones(const char* function_name) const { 1674 // Check the begin red zone. 1675 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy); 1676 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) { 1677 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) { 1678 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i); 1679 return false; 1680 } 1681 if (kCanary[j] == '\0') { 1682 j = 0; 1683 } else { 1684 j++; 1685 } 1686 } 1687 1688 // Check end region. 1689 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) { 1690 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) { 1691 size_t offset_from_buffer_start = 1692 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]); 1693 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this, 1694 offset_from_buffer_start); 1695 return false; 1696 } 1697 if (kCanary[j] == '\0') { 1698 j = 0; 1699 } else { 1700 j++; 1701 } 1702 } 1703 return true; 1704 } 1705 1706 // Location that canary value will be written before the guarded region. 1707 const char* StartRedZone() const { 1708 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this); 1709 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy)); 1710 } 1711 1712 // Return the interior embedded buffer. 1713 const uint8_t* BufferWithinRedZones() const { 1714 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2); 1715 return embedded_buf; 1716 } 1717 1718 // Location that canary value will be written after the guarded region. 1719 const char* EndRedZone() const { 1720 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this); 1721 size_t buf_len = LengthIncludingRedZones(original_length_); 1722 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2))); 1723 } 1724 1725 static constexpr size_t kRedZoneSize = 512; 1726 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2; 1727 1728 // Value written before and after the guarded array. 1729 static const char* const kCanary; 1730 1731 static constexpr uint32_t kGuardMagic = 0xffd5aa96; 1732 1733 const uint32_t magic_; 1734 const uLong adler_; 1735 void* const original_ptr_; 1736 const size_t original_length_; 1737 }; 1738 const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE"; 1739 1740 /* 1741 * =========================================================================== 1742 * JNI functions 1743 * =========================================================================== 1744 */ 1745 1746 class CheckJNI { 1747 public: 1748 static jint GetVersion(JNIEnv* env) { 1749 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 1750 ScopedObjectAccess soa(env); 1751 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1752 JniValueType args[1] = {{.E = env }}; 1753 if (sc.Check(soa, true, "E", args)) { 1754 JniValueType result; 1755 result.I = baseEnv(env)->GetVersion(env); 1756 if (sc.Check(soa, false, "I", &result)) { 1757 return result.I; 1758 } 1759 } 1760 return JNI_ERR; 1761 } 1762 1763 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) { 1764 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 1765 ScopedObjectAccess soa(env); 1766 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1767 JniValueType args[2] = {{.E = env }, {.p = vm}}; 1768 if (sc.Check(soa, true, "Ep", args)) { 1769 JniValueType result; 1770 result.i = baseEnv(env)->GetJavaVM(env, vm); 1771 if (sc.Check(soa, false, "i", &result)) { 1772 return result.i; 1773 } 1774 } 1775 return JNI_ERR; 1776 } 1777 1778 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) { 1779 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 1780 ScopedObjectAccess soa(env); 1781 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1782 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}}; 1783 if (sc.Check(soa, true, "EcpI", args)) { 1784 JniValueType result; 1785 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods); 1786 if (sc.Check(soa, false, "i", &result)) { 1787 return result.i; 1788 } 1789 } 1790 return JNI_ERR; 1791 } 1792 1793 static jint UnregisterNatives(JNIEnv* env, jclass c) { 1794 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 1795 ScopedObjectAccess soa(env); 1796 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1797 JniValueType args[2] = {{.E = env }, {.c = c}}; 1798 if (sc.Check(soa, true, "Ec", args)) { 1799 JniValueType result; 1800 result.i = baseEnv(env)->UnregisterNatives(env, c); 1801 if (sc.Check(soa, false, "i", &result)) { 1802 return result.i; 1803 } 1804 } 1805 return JNI_ERR; 1806 } 1807 1808 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) { 1809 CHECK_ATTACHED_THREAD(__FUNCTION__, JNIInvalidRefType); 1810 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to 1811 // know the object is invalid. The spec says that passing invalid objects or even ones that 1812 // are deleted isn't supported. 1813 ScopedObjectAccess soa(env); 1814 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1815 JniValueType args[2] = {{.E = env }, {.L = obj}}; 1816 if (sc.Check(soa, true, "EL", args)) { 1817 JniValueType result; 1818 result.w = baseEnv(env)->GetObjectRefType(env, obj); 1819 if (sc.Check(soa, false, "w", &result)) { 1820 return result.w; 1821 } 1822 } 1823 return JNIInvalidRefType; 1824 } 1825 1826 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, 1827 jsize bufLen) { 1828 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 1829 ScopedObjectAccess soa(env); 1830 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1831 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}}; 1832 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) { 1833 JniValueType result; 1834 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen); 1835 if (sc.Check(soa, false, "c", &result)) { 1836 return result.c; 1837 } 1838 } 1839 return nullptr; 1840 } 1841 1842 static jclass FindClass(JNIEnv* env, const char* name) { 1843 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 1844 ScopedObjectAccess soa(env); 1845 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1846 JniValueType args[2] = {{.E = env}, {.u = name}}; 1847 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) { 1848 JniValueType result; 1849 result.c = baseEnv(env)->FindClass(env, name); 1850 if (sc.Check(soa, false, "c", &result)) { 1851 return result.c; 1852 } 1853 } 1854 return nullptr; 1855 } 1856 1857 static jclass GetSuperclass(JNIEnv* env, jclass c) { 1858 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 1859 ScopedObjectAccess soa(env); 1860 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1861 JniValueType args[2] = {{.E = env}, {.c = c}}; 1862 if (sc.Check(soa, true, "Ec", args)) { 1863 JniValueType result; 1864 result.c = baseEnv(env)->GetSuperclass(env, c); 1865 if (sc.Check(soa, false, "c", &result)) { 1866 return result.c; 1867 } 1868 } 1869 return nullptr; 1870 } 1871 1872 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) { 1873 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE); 1874 ScopedObjectAccess soa(env); 1875 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1876 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}}; 1877 if (sc.Check(soa, true, "Ecc", args)) { 1878 JniValueType result; 1879 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2); 1880 if (sc.Check(soa, false, "b", &result)) { 1881 return result.b; 1882 } 1883 } 1884 return JNI_FALSE; 1885 } 1886 1887 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) { 1888 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 1889 ScopedObjectAccess soa(env); 1890 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1891 JniValueType args[2] = {{.E = env}, {.L = method}}; 1892 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) { 1893 JniValueType result; 1894 result.m = baseEnv(env)->FromReflectedMethod(env, method); 1895 if (sc.Check(soa, false, "m", &result)) { 1896 return result.m; 1897 } 1898 } 1899 return nullptr; 1900 } 1901 1902 static jfieldID FromReflectedField(JNIEnv* env, jobject field) { 1903 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 1904 ScopedObjectAccess soa(env); 1905 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1906 JniValueType args[2] = {{.E = env}, {.L = field}}; 1907 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) { 1908 JniValueType result; 1909 result.f = baseEnv(env)->FromReflectedField(env, field); 1910 if (sc.Check(soa, false, "f", &result)) { 1911 return result.f; 1912 } 1913 } 1914 return nullptr; 1915 } 1916 1917 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) { 1918 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 1919 ScopedObjectAccess soa(env); 1920 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1921 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.I = isStatic}}; 1922 if (sc.Check(soa, true, "Ecmb", args)) { 1923 JniValueType result; 1924 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic); 1925 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) { 1926 DCHECK(sc.CheckReflectedMethod(soa, result.L)); 1927 return result.L; 1928 } 1929 } 1930 return nullptr; 1931 } 1932 1933 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) { 1934 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 1935 ScopedObjectAccess soa(env); 1936 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1937 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.I = isStatic}}; 1938 if (sc.Check(soa, true, "Ecfb", args)) { 1939 JniValueType result; 1940 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic); 1941 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) { 1942 DCHECK(sc.CheckReflectedField(soa, result.L)); 1943 return result.L; 1944 } 1945 } 1946 return nullptr; 1947 } 1948 1949 static jint Throw(JNIEnv* env, jthrowable obj) { 1950 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 1951 ScopedObjectAccess soa(env); 1952 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1953 JniValueType args[2] = {{.E = env}, {.t = obj}}; 1954 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) { 1955 JniValueType result; 1956 result.i = baseEnv(env)->Throw(env, obj); 1957 if (sc.Check(soa, false, "i", &result)) { 1958 return result.i; 1959 } 1960 } 1961 return JNI_ERR; 1962 } 1963 1964 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) { 1965 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 1966 ScopedObjectAccess soa(env); 1967 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__); 1968 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}}; 1969 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) { 1970 JniValueType result; 1971 result.i = baseEnv(env)->ThrowNew(env, c, message); 1972 if (sc.Check(soa, false, "i", &result)) { 1973 return result.i; 1974 } 1975 } 1976 return JNI_ERR; 1977 } 1978 1979 static jthrowable ExceptionOccurred(JNIEnv* env) { 1980 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 1981 ScopedObjectAccess soa(env); 1982 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1983 JniValueType args[1] = {{.E = env}}; 1984 if (sc.Check(soa, true, "E", args)) { 1985 JniValueType result; 1986 result.t = baseEnv(env)->ExceptionOccurred(env); 1987 if (sc.Check(soa, false, "t", &result)) { 1988 return result.t; 1989 } 1990 } 1991 return nullptr; 1992 } 1993 1994 static void ExceptionDescribe(JNIEnv* env) { 1995 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__); 1996 ScopedObjectAccess soa(env); 1997 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1998 JniValueType args[1] = {{.E = env}}; 1999 if (sc.Check(soa, true, "E", args)) { 2000 JniValueType result; 2001 baseEnv(env)->ExceptionDescribe(env); 2002 result.V = nullptr; 2003 sc.Check(soa, false, "V", &result); 2004 } 2005 } 2006 2007 static void ExceptionClear(JNIEnv* env) { 2008 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__); 2009 ScopedObjectAccess soa(env); 2010 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 2011 JniValueType args[1] = {{.E = env}}; 2012 if (sc.Check(soa, true, "E", args)) { 2013 JniValueType result; 2014 baseEnv(env)->ExceptionClear(env); 2015 result.V = nullptr; 2016 sc.Check(soa, false, "V", &result); 2017 } 2018 } 2019 2020 static jboolean ExceptionCheck(JNIEnv* env) { 2021 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE); 2022 ScopedObjectAccess soa(env); 2023 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__); 2024 JniValueType args[1] = {{.E = env}}; 2025 if (sc.Check(soa, true, "E", args)) { 2026 JniValueType result; 2027 result.b = baseEnv(env)->ExceptionCheck(env); 2028 if (sc.Check(soa, false, "b", &result)) { 2029 return result.b; 2030 } 2031 } 2032 return JNI_FALSE; 2033 } 2034 2035 static void FatalError(JNIEnv* env, const char* msg) { 2036 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__); 2037 // The JNI specification doesn't say it's okay to call FatalError with a pending exception, 2038 // but you're about to abort anyway, and it's quite likely that you have a pending exception, 2039 // and it's not unimaginable that you don't know that you do. So we allow it. 2040 ScopedObjectAccess soa(env); 2041 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__); 2042 JniValueType args[2] = {{.E = env}, {.u = msg}}; 2043 if (sc.Check(soa, true, "Eu", args)) { 2044 JniValueType result; 2045 baseEnv(env)->FatalError(env, msg); 2046 // Unreachable. 2047 result.V = nullptr; 2048 sc.Check(soa, false, "V", &result); 2049 } 2050 } 2051 2052 static jint PushLocalFrame(JNIEnv* env, jint capacity) { 2053 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 2054 ScopedObjectAccess soa(env); 2055 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 2056 JniValueType args[2] = {{.E = env}, {.I = capacity}}; 2057 if (sc.Check(soa, true, "EI", args)) { 2058 JniValueType result; 2059 result.i = baseEnv(env)->PushLocalFrame(env, capacity); 2060 if (sc.Check(soa, false, "i", &result)) { 2061 return result.i; 2062 } 2063 } 2064 return JNI_ERR; 2065 } 2066 2067 static jobject PopLocalFrame(JNIEnv* env, jobject res) { 2068 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2069 ScopedObjectAccess soa(env); 2070 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 2071 JniValueType args[2] = {{.E = env}, {.L = res}}; 2072 if (sc.Check(soa, true, "EL", args)) { 2073 JniValueType result; 2074 result.L = baseEnv(env)->PopLocalFrame(env, res); 2075 sc.Check(soa, false, "L", &result); 2076 return result.L; 2077 } 2078 return nullptr; 2079 } 2080 2081 static jobject NewGlobalRef(JNIEnv* env, jobject obj) { 2082 return NewRef(__FUNCTION__, env, obj, kGlobal); 2083 } 2084 2085 static jobject NewLocalRef(JNIEnv* env, jobject obj) { 2086 return NewRef(__FUNCTION__, env, obj, kLocal); 2087 } 2088 2089 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) { 2090 return NewRef(__FUNCTION__, env, obj, kWeakGlobal); 2091 } 2092 2093 static void DeleteGlobalRef(JNIEnv* env, jobject obj) { 2094 DeleteRef(__FUNCTION__, env, obj, kGlobal); 2095 } 2096 2097 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) { 2098 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal); 2099 } 2100 2101 static void DeleteLocalRef(JNIEnv* env, jobject obj) { 2102 DeleteRef(__FUNCTION__, env, obj, kLocal); 2103 } 2104 2105 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) { 2106 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 2107 ScopedObjectAccess soa(env); 2108 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2109 JniValueType args[2] = {{.E = env}, {.I = capacity}}; 2110 if (sc.Check(soa, true, "EI", args)) { 2111 JniValueType result; 2112 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity); 2113 if (sc.Check(soa, false, "i", &result)) { 2114 return result.i; 2115 } 2116 } 2117 return JNI_ERR; 2118 } 2119 2120 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) { 2121 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE); 2122 ScopedObjectAccess soa(env); 2123 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2124 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}}; 2125 if (sc.Check(soa, true, "ELL", args)) { 2126 JniValueType result; 2127 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2); 2128 if (sc.Check(soa, false, "b", &result)) { 2129 return result.b; 2130 } 2131 } 2132 return JNI_FALSE; 2133 } 2134 2135 static jobject AllocObject(JNIEnv* env, jclass c) { 2136 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2137 ScopedObjectAccess soa(env); 2138 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2139 JniValueType args[2] = {{.E = env}, {.c = c}}; 2140 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) { 2141 JniValueType result; 2142 result.L = baseEnv(env)->AllocObject(env, c); 2143 if (sc.Check(soa, false, "L", &result)) { 2144 return result.L; 2145 } 2146 } 2147 return nullptr; 2148 } 2149 2150 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { 2151 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2152 ScopedObjectAccess soa(env); 2153 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2154 VarArgs rest(mid, vargs); 2155 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}}; 2156 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) && 2157 sc.CheckConstructor(mid)) { 2158 JniValueType result; 2159 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs); 2160 if (sc.Check(soa, false, "L", &result)) { 2161 return result.L; 2162 } 2163 } 2164 return nullptr; 2165 } 2166 2167 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) { 2168 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2169 va_list args; 2170 va_start(args, mid); 2171 jobject result = NewObjectV(env, c, mid, args); 2172 va_end(args); 2173 return result; 2174 } 2175 2176 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) { 2177 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2178 ScopedObjectAccess soa(env); 2179 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2180 VarArgs rest(mid, vargs); 2181 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}}; 2182 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) && 2183 sc.CheckConstructor(mid)) { 2184 JniValueType result; 2185 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs); 2186 if (sc.Check(soa, false, "L", &result)) { 2187 return result.L; 2188 } 2189 } 2190 return nullptr; 2191 } 2192 2193 static jclass GetObjectClass(JNIEnv* env, jobject obj) { 2194 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2195 ScopedObjectAccess soa(env); 2196 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2197 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2198 if (sc.Check(soa, true, "EL", args)) { 2199 JniValueType result; 2200 result.c = baseEnv(env)->GetObjectClass(env, obj); 2201 if (sc.Check(soa, false, "c", &result)) { 2202 return result.c; 2203 } 2204 } 2205 return nullptr; 2206 } 2207 2208 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) { 2209 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE); 2210 ScopedObjectAccess soa(env); 2211 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2212 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}}; 2213 if (sc.Check(soa, true, "ELc", args)) { 2214 JniValueType result; 2215 result.b = baseEnv(env)->IsInstanceOf(env, obj, c); 2216 if (sc.Check(soa, false, "b", &result)) { 2217 return result.b; 2218 } 2219 } 2220 return JNI_FALSE; 2221 } 2222 2223 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2224 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false); 2225 } 2226 2227 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2228 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true); 2229 } 2230 2231 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2232 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false); 2233 } 2234 2235 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2236 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true); 2237 } 2238 2239 #define FIELD_ACCESSORS(jtype, name, ptype, shorty, slot_sized_shorty) \ 2240 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \ 2241 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \ 2242 } \ 2243 \ 2244 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \ 2245 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \ 2246 } \ 2247 \ 2248 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \ 2249 JniValueType value; \ 2250 value.slot_sized_shorty = v; \ 2251 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \ 2252 } \ 2253 \ 2254 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \ 2255 JniValueType value; \ 2256 value.slot_sized_shorty = v; \ 2257 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \ 2258 } 2259 2260 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L, L) 2261 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z, I) 2262 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B, I) 2263 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C, I) 2264 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S, I) 2265 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I, I) 2266 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J, J) 2267 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F, F) 2268 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D, D) 2269 #undef FIELD_ACCESSORS 2270 2271 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, const jvalue* vargs) { 2272 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 2273 } 2274 2275 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, 2276 const jvalue* vargs) { 2277 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 2278 } 2279 2280 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) { 2281 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 2282 } 2283 2284 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { 2285 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 2286 } 2287 2288 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, 2289 va_list vargs) { 2290 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 2291 } 2292 2293 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { 2294 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 2295 } 2296 2297 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { 2298 va_list vargs; 2299 va_start(vargs, mid); 2300 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 2301 va_end(vargs); 2302 } 2303 2304 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) { 2305 va_list vargs; 2306 va_start(vargs, mid); 2307 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 2308 va_end(vargs); 2309 } 2310 2311 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) { 2312 va_list vargs; 2313 va_start(vargs, mid); 2314 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 2315 va_end(vargs); 2316 } 2317 2318 #define CALL(rtype, name, ptype, shorty) \ 2319 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, const jvalue* vargs) { \ 2320 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 2321 } \ 2322 \ 2323 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 2324 const jvalue* vargs) { \ 2325 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 2326 } \ 2327 \ 2328 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) { \ 2329 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 2330 } \ 2331 \ 2332 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \ 2333 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 2334 } \ 2335 \ 2336 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 2337 va_list vargs) { \ 2338 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 2339 } \ 2340 \ 2341 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \ 2342 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 2343 } \ 2344 \ 2345 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \ 2346 va_list vargs; \ 2347 va_start(vargs, mid); \ 2348 rtype result = \ 2349 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 2350 va_end(vargs); \ 2351 return result; \ 2352 } \ 2353 \ 2354 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 2355 ...) { \ 2356 va_list vargs; \ 2357 va_start(vargs, mid); \ 2358 rtype result = \ 2359 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 2360 va_end(vargs); \ 2361 return result; \ 2362 } \ 2363 \ 2364 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \ 2365 va_list vargs; \ 2366 va_start(vargs, mid); \ 2367 rtype result = \ 2368 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 2369 va_end(vargs); \ 2370 return result; \ 2371 } 2372 2373 CALL(jobject, Object, Primitive::kPrimNot, L) 2374 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z) 2375 CALL(jbyte, Byte, Primitive::kPrimByte, B) 2376 CALL(jchar, Char, Primitive::kPrimChar, C) 2377 CALL(jshort, Short, Primitive::kPrimShort, S) 2378 CALL(jint, Int, Primitive::kPrimInt, I) 2379 CALL(jlong, Long, Primitive::kPrimLong, J) 2380 CALL(jfloat, Float, Primitive::kPrimFloat, F) 2381 CALL(jdouble, Double, Primitive::kPrimDouble, D) 2382 #undef CALL 2383 2384 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) { 2385 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2386 ScopedObjectAccess soa(env); 2387 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2388 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}}; 2389 if (sc.Check(soa, true, "Epz", args)) { 2390 JniValueType result; 2391 result.s = baseEnv(env)->NewString(env, unicode_chars, len); 2392 if (sc.Check(soa, false, "s", &result)) { 2393 return result.s; 2394 } 2395 } 2396 return nullptr; 2397 } 2398 2399 static jstring NewStringUTF(JNIEnv* env, const char* chars) { 2400 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2401 ScopedObjectAccess soa(env); 2402 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__); 2403 JniValueType args[2] = {{.E = env}, {.u = chars}}; 2404 if (sc.Check(soa, true, "Eu", args)) { 2405 JniValueType result; 2406 // TODO: stale? show pointer and truncate string. 2407 result.s = baseEnv(env)->NewStringUTF(env, chars); 2408 if (sc.Check(soa, false, "s", &result)) { 2409 return result.s; 2410 } 2411 } 2412 return nullptr; 2413 } 2414 2415 static jsize GetStringLength(JNIEnv* env, jstring string) { 2416 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 2417 ScopedObjectAccess soa(env); 2418 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2419 JniValueType args[2] = {{.E = env}, {.s = string}}; 2420 if (sc.Check(soa, true, "Es", args)) { 2421 JniValueType result; 2422 result.z = baseEnv(env)->GetStringLength(env, string); 2423 if (sc.Check(soa, false, "z", &result)) { 2424 return result.z; 2425 } 2426 } 2427 return JNI_ERR; 2428 } 2429 2430 static jsize GetStringUTFLength(JNIEnv* env, jstring string) { 2431 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 2432 ScopedObjectAccess soa(env); 2433 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2434 JniValueType args[2] = {{.E = env}, {.s = string}}; 2435 if (sc.Check(soa, true, "Es", args)) { 2436 JniValueType result; 2437 result.z = baseEnv(env)->GetStringUTFLength(env, string); 2438 if (sc.Check(soa, false, "z", &result)) { 2439 return result.z; 2440 } 2441 } 2442 return JNI_ERR; 2443 } 2444 2445 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) { 2446 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string, 2447 is_copy, false, false)); 2448 } 2449 2450 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) { 2451 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string, 2452 is_copy, true, false)); 2453 } 2454 2455 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) { 2456 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string, 2457 is_copy, false, true)); 2458 } 2459 2460 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) { 2461 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false); 2462 } 2463 2464 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) { 2465 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false); 2466 } 2467 2468 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) { 2469 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true); 2470 } 2471 2472 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) { 2473 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__); 2474 ScopedObjectAccess soa(env); 2475 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2476 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}}; 2477 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 2478 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 2479 if (sc.Check(soa, true, "EsIIp", args)) { 2480 baseEnv(env)->GetStringRegion(env, string, start, len, buf); 2481 JniValueType result; 2482 result.V = nullptr; 2483 sc.Check(soa, false, "V", &result); 2484 } 2485 } 2486 2487 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) { 2488 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__); 2489 ScopedObjectAccess soa(env); 2490 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2491 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}}; 2492 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 2493 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 2494 if (sc.Check(soa, true, "EsIIp", args)) { 2495 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf); 2496 JniValueType result; 2497 result.V = nullptr; 2498 sc.Check(soa, false, "V", &result); 2499 } 2500 } 2501 2502 static jsize GetArrayLength(JNIEnv* env, jarray array) { 2503 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 2504 ScopedObjectAccess soa(env); 2505 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2506 JniValueType args[2] = {{.E = env}, {.a = array}}; 2507 if (sc.Check(soa, true, "Ea", args)) { 2508 JniValueType result; 2509 result.z = baseEnv(env)->GetArrayLength(env, array); 2510 if (sc.Check(soa, false, "z", &result)) { 2511 return result.z; 2512 } 2513 } 2514 return JNI_ERR; 2515 } 2516 2517 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class, 2518 jobject initial_element) { 2519 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2520 ScopedObjectAccess soa(env); 2521 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2522 JniValueType args[4] = 2523 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}}; 2524 if (sc.Check(soa, true, "EzcL", args)) { 2525 JniValueType result; 2526 // Note: assignability tests of initial_element are done in the base implementation. 2527 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element); 2528 if (sc.Check(soa, false, "a", &result)) { 2529 return down_cast<jobjectArray>(result.a); 2530 } 2531 } 2532 return nullptr; 2533 } 2534 2535 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) { 2536 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2537 ScopedObjectAccess soa(env); 2538 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2539 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}}; 2540 if (sc.Check(soa, true, "Eaz", args)) { 2541 JniValueType result; 2542 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index); 2543 if (sc.Check(soa, false, "L", &result)) { 2544 return result.L; 2545 } 2546 } 2547 return nullptr; 2548 } 2549 2550 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) { 2551 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__); 2552 ScopedObjectAccess soa(env); 2553 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2554 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}}; 2555 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in 2556 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result 2557 // in ArrayStoreExceptions. 2558 if (sc.Check(soa, true, "EaIL", args)) { 2559 baseEnv(env)->SetObjectArrayElement(env, array, index, value); 2560 JniValueType result; 2561 result.V = nullptr; 2562 sc.Check(soa, false, "V", &result); 2563 } 2564 } 2565 2566 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) { 2567 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2568 Primitive::kPrimBoolean)); 2569 } 2570 2571 static jbyteArray NewByteArray(JNIEnv* env, jsize length) { 2572 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2573 Primitive::kPrimByte)); 2574 } 2575 2576 static jcharArray NewCharArray(JNIEnv* env, jsize length) { 2577 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2578 Primitive::kPrimChar)); 2579 } 2580 2581 static jshortArray NewShortArray(JNIEnv* env, jsize length) { 2582 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2583 Primitive::kPrimShort)); 2584 } 2585 2586 static jintArray NewIntArray(JNIEnv* env, jsize length) { 2587 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt)); 2588 } 2589 2590 static jlongArray NewLongArray(JNIEnv* env, jsize length) { 2591 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2592 Primitive::kPrimLong)); 2593 } 2594 2595 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) { 2596 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2597 Primitive::kPrimFloat)); 2598 } 2599 2600 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) { 2601 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2602 Primitive::kPrimDouble)); 2603 } 2604 2605 // NOLINT added to avoid wrong warning/fix from clang-tidy. 2606 #define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \ 2607 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \ 2608 return reinterpret_cast<ctype*>( /* NOLINT */ \ 2609 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \ 2610 } \ 2611 \ 2612 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \ 2613 jint mode) { \ 2614 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \ 2615 } \ 2616 \ 2617 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \ 2618 ctype* buf) { /* NOLINT */ \ 2619 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \ 2620 } \ 2621 \ 2622 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \ 2623 const ctype* buf) { \ 2624 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \ 2625 } 2626 2627 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean) 2628 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte) 2629 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar) 2630 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort) 2631 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt) 2632 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong) 2633 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat) 2634 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble) 2635 #undef PRIMITIVE_ARRAY_FUNCTIONS 2636 2637 static jint MonitorEnter(JNIEnv* env, jobject obj) { 2638 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 2639 ScopedObjectAccess soa(env); 2640 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2641 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2642 if (sc.Check(soa, true, "EL", args)) { 2643 if (obj != nullptr) { 2644 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj); 2645 } 2646 JniValueType result; 2647 result.i = baseEnv(env)->MonitorEnter(env, obj); 2648 if (sc.Check(soa, false, "i", &result)) { 2649 return result.i; 2650 } 2651 } 2652 return JNI_ERR; 2653 } 2654 2655 static jint MonitorExit(JNIEnv* env, jobject obj) { 2656 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 2657 ScopedObjectAccess soa(env); 2658 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 2659 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2660 if (sc.Check(soa, true, "EL", args)) { 2661 if (obj != nullptr) { 2662 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj); 2663 } 2664 JniValueType result; 2665 result.i = baseEnv(env)->MonitorExit(env, obj); 2666 if (sc.Check(soa, false, "i", &result)) { 2667 return result.i; 2668 } 2669 } 2670 return JNI_ERR; 2671 } 2672 2673 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) { 2674 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2675 ScopedObjectAccess soa(env); 2676 ScopedCheck sc(kFlag_CritGet, __FUNCTION__); 2677 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}}; 2678 if (sc.Check(soa, true, "Eap", args)) { 2679 JniValueType result; 2680 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy); 2681 if (ptr != nullptr && soa.ForceCopy()) { 2682 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr); 2683 } 2684 result.p = ptr; 2685 if (sc.Check(soa, false, "p", &result)) { 2686 return const_cast<void*>(result.p); 2687 } 2688 } 2689 return nullptr; 2690 } 2691 2692 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) { 2693 CHECK_ATTACHED_THREAD_VOID(__FUNCTION__); 2694 ScopedObjectAccess soa(env); 2695 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__); 2696 sc.CheckNonNull(carray); 2697 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}}; 2698 if (sc.Check(soa, true, "Eapr", args)) { 2699 if (soa.ForceCopy()) { 2700 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode); 2701 } 2702 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode); 2703 JniValueType result; 2704 result.V = nullptr; 2705 sc.Check(soa, false, "V", &result); 2706 } 2707 } 2708 2709 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) { 2710 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2711 ScopedObjectAccess soa(env); 2712 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2713 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}}; 2714 if (sc.Check(soa, true, "EpJ", args)) { 2715 JniValueType result; 2716 // Note: the validity of address and capacity are checked in the base implementation. 2717 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity); 2718 if (sc.Check(soa, false, "L", &result)) { 2719 return result.L; 2720 } 2721 } 2722 return nullptr; 2723 } 2724 2725 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) { 2726 CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr); 2727 ScopedObjectAccess soa(env); 2728 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2729 JniValueType args[2] = {{.E = env}, {.L = buf}}; 2730 if (sc.Check(soa, true, "EL", args)) { 2731 JniValueType result; 2732 // Note: this is implemented in the base environment by a GetLongField which will sanity 2733 // check the type of buf in GetLongField above. 2734 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf); 2735 if (sc.Check(soa, false, "p", &result)) { 2736 return const_cast<void*>(result.p); 2737 } 2738 } 2739 return nullptr; 2740 } 2741 2742 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) { 2743 CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR); 2744 ScopedObjectAccess soa(env); 2745 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2746 JniValueType args[2] = {{.E = env}, {.L = buf}}; 2747 if (sc.Check(soa, true, "EL", args)) { 2748 JniValueType result; 2749 // Note: this is implemented in the base environment by a GetIntField which will sanity 2750 // check the type of buf in GetIntField above. 2751 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf); 2752 if (sc.Check(soa, false, "J", &result)) { 2753 return result.J; 2754 } 2755 } 2756 return JNI_ERR; 2757 } 2758 2759 private: 2760 static JavaVMExt* GetJavaVMExt(JNIEnv* env) { 2761 return reinterpret_cast<JNIEnvExt*>(env)->GetVm(); 2762 } 2763 2764 static const JNINativeInterface* baseEnv(JNIEnv* env) { 2765 return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions(); 2766 } 2767 2768 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) { 2769 CHECK_ATTACHED_THREAD(function_name, nullptr); 2770 ScopedObjectAccess soa(env); 2771 ScopedCheck sc(kFlag_Default, function_name); 2772 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2773 if (sc.Check(soa, true, "EL", args)) { 2774 JniValueType result; 2775 switch (kind) { 2776 case kGlobal: 2777 result.L = baseEnv(env)->NewGlobalRef(env, obj); 2778 break; 2779 case kLocal: 2780 result.L = baseEnv(env)->NewLocalRef(env, obj); 2781 break; 2782 case kWeakGlobal: 2783 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj); 2784 break; 2785 default: 2786 LOG(FATAL) << "Unexpected reference kind: " << kind; 2787 } 2788 if (sc.Check(soa, false, "L", &result)) { 2789 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE); 2790 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L)); 2791 return result.L; 2792 } 2793 } 2794 return nullptr; 2795 } 2796 2797 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) { 2798 CHECK_ATTACHED_THREAD_VOID(function_name); 2799 ScopedObjectAccess soa(env); 2800 ScopedCheck sc(kFlag_ExcepOkay, function_name); 2801 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2802 sc.Check(soa, true, "EL", args); 2803 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) { 2804 JniValueType result; 2805 switch (kind) { 2806 case kGlobal: 2807 baseEnv(env)->DeleteGlobalRef(env, obj); 2808 break; 2809 case kLocal: 2810 baseEnv(env)->DeleteLocalRef(env, obj); 2811 break; 2812 case kWeakGlobal: 2813 baseEnv(env)->DeleteWeakGlobalRef(env, obj); 2814 break; 2815 default: 2816 LOG(FATAL) << "Unexpected reference kind: " << kind; 2817 } 2818 result.V = nullptr; 2819 sc.Check(soa, false, "V", &result); 2820 } 2821 } 2822 2823 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c, 2824 const char* name, const char* sig, bool is_static) { 2825 CHECK_ATTACHED_THREAD(function_name, nullptr); 2826 ScopedObjectAccess soa(env); 2827 ScopedCheck sc(kFlag_Default, function_name); 2828 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}}; 2829 if (sc.Check(soa, true, "Ecuu", args)) { 2830 JniValueType result; 2831 if (is_static) { 2832 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig); 2833 } else { 2834 result.m = baseEnv(env)->GetMethodID(env, c, name, sig); 2835 } 2836 if (sc.Check(soa, false, "m", &result)) { 2837 return result.m; 2838 } 2839 } 2840 return nullptr; 2841 } 2842 2843 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c, 2844 const char* name, const char* sig, bool is_static) { 2845 CHECK_ATTACHED_THREAD(function_name, nullptr); 2846 ScopedObjectAccess soa(env); 2847 ScopedCheck sc(kFlag_Default, function_name); 2848 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}}; 2849 if (sc.Check(soa, true, "Ecuu", args)) { 2850 JniValueType result; 2851 if (is_static) { 2852 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig); 2853 } else { 2854 result.f = baseEnv(env)->GetFieldID(env, c, name, sig); 2855 } 2856 if (sc.Check(soa, false, "f", &result)) { 2857 return result.f; 2858 } 2859 } 2860 return nullptr; 2861 } 2862 2863 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid, 2864 bool is_static, Primitive::Type type) { 2865 CHECK_ATTACHED_THREAD(function_name, JniValueType()); 2866 ScopedObjectAccess soa(env); 2867 ScopedCheck sc(kFlag_Default, function_name); 2868 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}}; 2869 JniValueType result; 2870 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) && 2871 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) { 2872 const char* result_check = nullptr; 2873 switch (type) { 2874 case Primitive::kPrimNot: 2875 if (is_static) { 2876 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid); 2877 } else { 2878 result.L = baseEnv(env)->GetObjectField(env, obj, fid); 2879 } 2880 result_check = "L"; 2881 break; 2882 case Primitive::kPrimBoolean: 2883 if (is_static) { 2884 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid); 2885 } else { 2886 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid); 2887 } 2888 result_check = "Z"; 2889 break; 2890 case Primitive::kPrimByte: 2891 if (is_static) { 2892 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid); 2893 } else { 2894 result.B = baseEnv(env)->GetByteField(env, obj, fid); 2895 } 2896 result_check = "B"; 2897 break; 2898 case Primitive::kPrimChar: 2899 if (is_static) { 2900 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid); 2901 } else { 2902 result.C = baseEnv(env)->GetCharField(env, obj, fid); 2903 } 2904 result_check = "C"; 2905 break; 2906 case Primitive::kPrimShort: 2907 if (is_static) { 2908 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid); 2909 } else { 2910 result.S = baseEnv(env)->GetShortField(env, obj, fid); 2911 } 2912 result_check = "S"; 2913 break; 2914 case Primitive::kPrimInt: 2915 if (is_static) { 2916 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid); 2917 } else { 2918 result.I = baseEnv(env)->GetIntField(env, obj, fid); 2919 } 2920 result_check = "I"; 2921 break; 2922 case Primitive::kPrimLong: 2923 if (is_static) { 2924 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid); 2925 } else { 2926 result.J = baseEnv(env)->GetLongField(env, obj, fid); 2927 } 2928 result_check = "J"; 2929 break; 2930 case Primitive::kPrimFloat: 2931 if (is_static) { 2932 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid); 2933 } else { 2934 result.F = baseEnv(env)->GetFloatField(env, obj, fid); 2935 } 2936 result_check = "F"; 2937 break; 2938 case Primitive::kPrimDouble: 2939 if (is_static) { 2940 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid); 2941 } else { 2942 result.D = baseEnv(env)->GetDoubleField(env, obj, fid); 2943 } 2944 result_check = "D"; 2945 break; 2946 case Primitive::kPrimVoid: 2947 LOG(FATAL) << "Unexpected type: " << type; 2948 UNREACHABLE(); 2949 } 2950 if (sc.Check(soa, false, result_check, &result)) { 2951 return result; 2952 } 2953 } 2954 result.J = 0; 2955 return result; 2956 } 2957 2958 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid, 2959 bool is_static, Primitive::Type type, JniValueType value) { 2960 CHECK_ATTACHED_THREAD_VOID(function_name); 2961 ScopedObjectAccess soa(env); 2962 ScopedCheck sc(kFlag_Default, function_name); 2963 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value}; 2964 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f', 2965 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'}; 2966 if (sc.Check(soa, true, sig, args) && 2967 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) { 2968 switch (type) { 2969 case Primitive::kPrimNot: 2970 if (is_static) { 2971 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L); 2972 } else { 2973 baseEnv(env)->SetObjectField(env, obj, fid, value.L); 2974 } 2975 break; 2976 case Primitive::kPrimBoolean: 2977 if (is_static) { 2978 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z); 2979 } else { 2980 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z); 2981 } 2982 break; 2983 case Primitive::kPrimByte: 2984 if (is_static) { 2985 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B); 2986 } else { 2987 baseEnv(env)->SetByteField(env, obj, fid, value.B); 2988 } 2989 break; 2990 case Primitive::kPrimChar: 2991 if (is_static) { 2992 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C); 2993 } else { 2994 baseEnv(env)->SetCharField(env, obj, fid, value.C); 2995 } 2996 break; 2997 case Primitive::kPrimShort: 2998 if (is_static) { 2999 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S); 3000 } else { 3001 baseEnv(env)->SetShortField(env, obj, fid, value.S); 3002 } 3003 break; 3004 case Primitive::kPrimInt: 3005 if (is_static) { 3006 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I); 3007 } else { 3008 baseEnv(env)->SetIntField(env, obj, fid, value.I); 3009 } 3010 break; 3011 case Primitive::kPrimLong: 3012 if (is_static) { 3013 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J); 3014 } else { 3015 baseEnv(env)->SetLongField(env, obj, fid, value.J); 3016 } 3017 break; 3018 case Primitive::kPrimFloat: 3019 if (is_static) { 3020 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F); 3021 } else { 3022 baseEnv(env)->SetFloatField(env, obj, fid, value.F); 3023 } 3024 break; 3025 case Primitive::kPrimDouble: 3026 if (is_static) { 3027 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D); 3028 } else { 3029 baseEnv(env)->SetDoubleField(env, obj, fid, value.D); 3030 } 3031 break; 3032 case Primitive::kPrimVoid: 3033 LOG(FATAL) << "Unexpected type: " << type; 3034 UNREACHABLE(); 3035 } 3036 JniValueType result; 3037 result.V = nullptr; 3038 sc.Check(soa, false, "V", &result); 3039 } 3040 } 3041 3042 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj, 3043 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs) 3044 REQUIRES_SHARED(Locks::mutator_lock_) { 3045 bool checked; 3046 switch (invoke) { 3047 case kVirtual: { 3048 DCHECK(c == nullptr); 3049 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}}; 3050 checked = sc.Check(soa, true, "ELm.", args); 3051 break; 3052 } 3053 case kDirect: { 3054 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}}; 3055 checked = sc.Check(soa, true, "ELcm.", args); 3056 break; 3057 } 3058 case kStatic: { 3059 DCHECK(obj == nullptr); 3060 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}}; 3061 checked = sc.Check(soa, true, "Ecm.", args); 3062 break; 3063 } 3064 default: 3065 LOG(FATAL) << "Unexpected invoke: " << invoke; 3066 checked = false; 3067 break; 3068 } 3069 return checked; 3070 } 3071 3072 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c, 3073 jmethodID mid, const jvalue* vargs, Primitive::Type type, 3074 InvokeType invoke) { 3075 CHECK_ATTACHED_THREAD(function_name, JniValueType()); 3076 ScopedObjectAccess soa(env); 3077 ScopedCheck sc(kFlag_Default, function_name); 3078 JniValueType result; 3079 VarArgs rest(mid, vargs); 3080 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) && 3081 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) { 3082 const char* result_check; 3083 switch (type) { 3084 case Primitive::kPrimNot: 3085 result_check = "L"; 3086 switch (invoke) { 3087 case kVirtual: 3088 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs); 3089 break; 3090 case kDirect: 3091 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs); 3092 break; 3093 case kStatic: 3094 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs); 3095 break; 3096 default: 3097 break; 3098 } 3099 break; 3100 case Primitive::kPrimBoolean: 3101 result_check = "Z"; 3102 switch (invoke) { 3103 case kVirtual: 3104 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs); 3105 break; 3106 case kDirect: 3107 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs); 3108 break; 3109 case kStatic: 3110 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs); 3111 break; 3112 default: 3113 break; 3114 } 3115 break; 3116 case Primitive::kPrimByte: 3117 result_check = "B"; 3118 switch (invoke) { 3119 case kVirtual: 3120 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs); 3121 break; 3122 case kDirect: 3123 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs); 3124 break; 3125 case kStatic: 3126 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs); 3127 break; 3128 default: 3129 break; 3130 } 3131 break; 3132 case Primitive::kPrimChar: 3133 result_check = "C"; 3134 switch (invoke) { 3135 case kVirtual: 3136 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs); 3137 break; 3138 case kDirect: 3139 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs); 3140 break; 3141 case kStatic: 3142 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs); 3143 break; 3144 default: 3145 break; 3146 } 3147 break; 3148 case Primitive::kPrimShort: 3149 result_check = "S"; 3150 switch (invoke) { 3151 case kVirtual: 3152 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs); 3153 break; 3154 case kDirect: 3155 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs); 3156 break; 3157 case kStatic: 3158 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs); 3159 break; 3160 default: 3161 break; 3162 } 3163 break; 3164 case Primitive::kPrimInt: 3165 result_check = "I"; 3166 switch (invoke) { 3167 case kVirtual: 3168 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs); 3169 break; 3170 case kDirect: 3171 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs); 3172 break; 3173 case kStatic: 3174 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs); 3175 break; 3176 default: 3177 break; 3178 } 3179 break; 3180 case Primitive::kPrimLong: 3181 result_check = "J"; 3182 switch (invoke) { 3183 case kVirtual: 3184 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs); 3185 break; 3186 case kDirect: 3187 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs); 3188 break; 3189 case kStatic: 3190 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs); 3191 break; 3192 default: 3193 break; 3194 } 3195 break; 3196 case Primitive::kPrimFloat: 3197 result_check = "F"; 3198 switch (invoke) { 3199 case kVirtual: 3200 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs); 3201 break; 3202 case kDirect: 3203 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs); 3204 break; 3205 case kStatic: 3206 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs); 3207 break; 3208 default: 3209 break; 3210 } 3211 break; 3212 case Primitive::kPrimDouble: 3213 result_check = "D"; 3214 switch (invoke) { 3215 case kVirtual: 3216 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs); 3217 break; 3218 case kDirect: 3219 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs); 3220 break; 3221 case kStatic: 3222 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs); 3223 break; 3224 default: 3225 break; 3226 } 3227 break; 3228 case Primitive::kPrimVoid: 3229 result_check = "V"; 3230 result.V = nullptr; 3231 switch (invoke) { 3232 case kVirtual: 3233 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs); 3234 break; 3235 case kDirect: 3236 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs); 3237 break; 3238 case kStatic: 3239 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs); 3240 break; 3241 default: 3242 LOG(FATAL) << "Unexpected invoke: " << invoke; 3243 } 3244 break; 3245 default: 3246 LOG(FATAL) << "Unexpected return type: " << type; 3247 result_check = nullptr; 3248 } 3249 if (sc.Check(soa, false, result_check, &result)) { 3250 return result; 3251 } 3252 } 3253 result.J = 0; 3254 return result; 3255 } 3256 3257 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c, 3258 jmethodID mid, va_list vargs, Primitive::Type type, 3259 InvokeType invoke) { 3260 CHECK_ATTACHED_THREAD(function_name, JniValueType()); 3261 ScopedObjectAccess soa(env); 3262 ScopedCheck sc(kFlag_Default, function_name); 3263 JniValueType result; 3264 VarArgs rest(mid, vargs); 3265 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) && 3266 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) { 3267 const char* result_check; 3268 switch (type) { 3269 case Primitive::kPrimNot: 3270 result_check = "L"; 3271 switch (invoke) { 3272 case kVirtual: 3273 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs); 3274 break; 3275 case kDirect: 3276 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs); 3277 break; 3278 case kStatic: 3279 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs); 3280 break; 3281 default: 3282 LOG(FATAL) << "Unexpected invoke: " << invoke; 3283 } 3284 break; 3285 case Primitive::kPrimBoolean: 3286 result_check = "Z"; 3287 switch (invoke) { 3288 case kVirtual: 3289 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs); 3290 break; 3291 case kDirect: 3292 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs); 3293 break; 3294 case kStatic: 3295 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs); 3296 break; 3297 default: 3298 LOG(FATAL) << "Unexpected invoke: " << invoke; 3299 } 3300 break; 3301 case Primitive::kPrimByte: 3302 result_check = "B"; 3303 switch (invoke) { 3304 case kVirtual: 3305 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs); 3306 break; 3307 case kDirect: 3308 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs); 3309 break; 3310 case kStatic: 3311 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs); 3312 break; 3313 default: 3314 LOG(FATAL) << "Unexpected invoke: " << invoke; 3315 } 3316 break; 3317 case Primitive::kPrimChar: 3318 result_check = "C"; 3319 switch (invoke) { 3320 case kVirtual: 3321 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs); 3322 break; 3323 case kDirect: 3324 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs); 3325 break; 3326 case kStatic: 3327 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs); 3328 break; 3329 default: 3330 LOG(FATAL) << "Unexpected invoke: " << invoke; 3331 } 3332 break; 3333 case Primitive::kPrimShort: 3334 result_check = "S"; 3335 switch (invoke) { 3336 case kVirtual: 3337 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs); 3338 break; 3339 case kDirect: 3340 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs); 3341 break; 3342 case kStatic: 3343 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs); 3344 break; 3345 default: 3346 LOG(FATAL) << "Unexpected invoke: " << invoke; 3347 } 3348 break; 3349 case Primitive::kPrimInt: 3350 result_check = "I"; 3351 switch (invoke) { 3352 case kVirtual: 3353 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs); 3354 break; 3355 case kDirect: 3356 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs); 3357 break; 3358 case kStatic: 3359 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs); 3360 break; 3361 default: 3362 LOG(FATAL) << "Unexpected invoke: " << invoke; 3363 } 3364 break; 3365 case Primitive::kPrimLong: 3366 result_check = "J"; 3367 switch (invoke) { 3368 case kVirtual: 3369 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs); 3370 break; 3371 case kDirect: 3372 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs); 3373 break; 3374 case kStatic: 3375 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs); 3376 break; 3377 default: 3378 LOG(FATAL) << "Unexpected invoke: " << invoke; 3379 } 3380 break; 3381 case Primitive::kPrimFloat: 3382 result_check = "F"; 3383 switch (invoke) { 3384 case kVirtual: 3385 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs); 3386 break; 3387 case kDirect: 3388 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs); 3389 break; 3390 case kStatic: 3391 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs); 3392 break; 3393 default: 3394 LOG(FATAL) << "Unexpected invoke: " << invoke; 3395 } 3396 break; 3397 case Primitive::kPrimDouble: 3398 result_check = "D"; 3399 switch (invoke) { 3400 case kVirtual: 3401 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs); 3402 break; 3403 case kDirect: 3404 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs); 3405 break; 3406 case kStatic: 3407 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs); 3408 break; 3409 default: 3410 LOG(FATAL) << "Unexpected invoke: " << invoke; 3411 } 3412 break; 3413 case Primitive::kPrimVoid: 3414 result_check = "V"; 3415 result.V = nullptr; 3416 switch (invoke) { 3417 case kVirtual: 3418 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs); 3419 break; 3420 case kDirect: 3421 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs); 3422 break; 3423 case kStatic: 3424 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs); 3425 break; 3426 default: 3427 LOG(FATAL) << "Unexpected invoke: " << invoke; 3428 } 3429 break; 3430 default: 3431 LOG(FATAL) << "Unexpected return type: " << type; 3432 result_check = nullptr; 3433 } 3434 if (sc.Check(soa, false, result_check, &result)) { 3435 return result; 3436 } 3437 } 3438 result.J = 0; 3439 return result; 3440 } 3441 3442 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string, 3443 jboolean* is_copy, bool utf, bool critical) { 3444 CHECK_ATTACHED_THREAD(function_name, nullptr); 3445 ScopedObjectAccess soa(env); 3446 int flags = critical ? kFlag_CritGet : kFlag_CritOkay; 3447 ScopedCheck sc(flags, function_name); 3448 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}}; 3449 if (sc.Check(soa, true, "Esp", args)) { 3450 JniValueType result; 3451 void* ptr; 3452 if (utf) { 3453 CHECK(!critical); 3454 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy)); 3455 result.u = reinterpret_cast<char*>(ptr); 3456 } else { 3457 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) : 3458 baseEnv(env)->GetStringChars(env, string, is_copy)); 3459 result.p = ptr; 3460 } 3461 // TODO: could we be smarter about not copying when local_is_copy? 3462 if (ptr != nullptr && soa.ForceCopy()) { 3463 if (utf) { 3464 size_t length_in_bytes = strlen(result.u) + 1; 3465 result.u = 3466 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false)); 3467 } else { 3468 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2; 3469 result.p = 3470 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false)); 3471 } 3472 if (is_copy != nullptr) { 3473 *is_copy = JNI_TRUE; 3474 } 3475 } 3476 if (sc.Check(soa, false, utf ? "u" : "p", &result)) { 3477 return utf ? result.u : result.p; 3478 } 3479 } 3480 return nullptr; 3481 } 3482 3483 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string, 3484 const void* chars, bool utf, bool critical) { 3485 CHECK_ATTACHED_THREAD_VOID(function_name); 3486 ScopedObjectAccess soa(env); 3487 int flags = kFlag_ExcepOkay | kFlag_Release; 3488 if (critical) { 3489 flags |= kFlag_CritRelease; 3490 } 3491 ScopedCheck sc(flags, function_name); 3492 sc.CheckNonNull(chars); 3493 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false); 3494 if (force_copy_ok && soa.ForceCopy()) { 3495 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars))); 3496 } 3497 if (force_copy_ok) { 3498 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}}; 3499 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) { 3500 if (utf) { 3501 CHECK(!critical); 3502 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars)); 3503 } else { 3504 if (critical) { 3505 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars)); 3506 } else { 3507 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars)); 3508 } 3509 } 3510 JniValueType result; 3511 sc.Check(soa, false, "V", &result); 3512 } 3513 } 3514 } 3515 3516 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length, 3517 Primitive::Type type) { 3518 CHECK_ATTACHED_THREAD(function_name, nullptr); 3519 ScopedObjectAccess soa(env); 3520 ScopedCheck sc(kFlag_Default, function_name); 3521 JniValueType args[2] = {{.E = env}, {.z = length}}; 3522 if (sc.Check(soa, true, "Ez", args)) { 3523 JniValueType result; 3524 switch (type) { 3525 case Primitive::kPrimBoolean: 3526 result.a = baseEnv(env)->NewBooleanArray(env, length); 3527 break; 3528 case Primitive::kPrimByte: 3529 result.a = baseEnv(env)->NewByteArray(env, length); 3530 break; 3531 case Primitive::kPrimChar: 3532 result.a = baseEnv(env)->NewCharArray(env, length); 3533 break; 3534 case Primitive::kPrimShort: 3535 result.a = baseEnv(env)->NewShortArray(env, length); 3536 break; 3537 case Primitive::kPrimInt: 3538 result.a = baseEnv(env)->NewIntArray(env, length); 3539 break; 3540 case Primitive::kPrimLong: 3541 result.a = baseEnv(env)->NewLongArray(env, length); 3542 break; 3543 case Primitive::kPrimFloat: 3544 result.a = baseEnv(env)->NewFloatArray(env, length); 3545 break; 3546 case Primitive::kPrimDouble: 3547 result.a = baseEnv(env)->NewDoubleArray(env, length); 3548 break; 3549 default: 3550 LOG(FATAL) << "Unexpected primitive type: " << type; 3551 } 3552 if (sc.Check(soa, false, "a", &result)) { 3553 return result.a; 3554 } 3555 } 3556 return nullptr; 3557 } 3558 3559 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type, 3560 JNIEnv* env, jarray array, jboolean* is_copy) { 3561 CHECK_ATTACHED_THREAD(function_name, nullptr); 3562 ScopedObjectAccess soa(env); 3563 ScopedCheck sc(kFlag_Default, function_name); 3564 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}}; 3565 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3566 JniValueType result; 3567 void* ptr = nullptr; 3568 switch (type) { 3569 case Primitive::kPrimBoolean: 3570 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array), 3571 is_copy); 3572 break; 3573 case Primitive::kPrimByte: 3574 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy); 3575 break; 3576 case Primitive::kPrimChar: 3577 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy); 3578 break; 3579 case Primitive::kPrimShort: 3580 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy); 3581 break; 3582 case Primitive::kPrimInt: 3583 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy); 3584 break; 3585 case Primitive::kPrimLong: 3586 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy); 3587 break; 3588 case Primitive::kPrimFloat: 3589 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy); 3590 break; 3591 case Primitive::kPrimDouble: 3592 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy); 3593 break; 3594 default: 3595 LOG(FATAL) << "Unexpected primitive type: " << type; 3596 } 3597 if (ptr != nullptr && soa.ForceCopy()) { 3598 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr); 3599 if (is_copy != nullptr) { 3600 *is_copy = JNI_TRUE; 3601 } 3602 } 3603 result.p = ptr; 3604 if (sc.Check(soa, false, "p", &result)) { 3605 return const_cast<void*>(result.p); 3606 } 3607 } 3608 return nullptr; 3609 } 3610 3611 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type, 3612 JNIEnv* env, jarray array, void* elems, jint mode) { 3613 CHECK_ATTACHED_THREAD_VOID(function_name); 3614 ScopedObjectAccess soa(env); 3615 ScopedCheck sc(kFlag_ExcepOkay, function_name); 3616 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3617 if (soa.ForceCopy()) { 3618 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode); 3619 } 3620 if (!soa.ForceCopy() || elems != nullptr) { 3621 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}}; 3622 if (sc.Check(soa, true, "Eapr", args)) { 3623 switch (type) { 3624 case Primitive::kPrimBoolean: 3625 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array), 3626 reinterpret_cast<jboolean*>(elems), mode); 3627 break; 3628 case Primitive::kPrimByte: 3629 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array), 3630 reinterpret_cast<jbyte*>(elems), mode); 3631 break; 3632 case Primitive::kPrimChar: 3633 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array), 3634 reinterpret_cast<jchar*>(elems), mode); 3635 break; 3636 case Primitive::kPrimShort: 3637 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array), 3638 reinterpret_cast<jshort*>(elems), mode); 3639 break; 3640 case Primitive::kPrimInt: 3641 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array), 3642 reinterpret_cast<jint*>(elems), mode); 3643 break; 3644 case Primitive::kPrimLong: 3645 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array), 3646 reinterpret_cast<jlong*>(elems), mode); 3647 break; 3648 case Primitive::kPrimFloat: 3649 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array), 3650 reinterpret_cast<jfloat*>(elems), mode); 3651 break; 3652 case Primitive::kPrimDouble: 3653 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array), 3654 reinterpret_cast<jdouble*>(elems), mode); 3655 break; 3656 default: 3657 LOG(FATAL) << "Unexpected primitive type: " << type; 3658 } 3659 JniValueType result; 3660 result.V = nullptr; 3661 sc.Check(soa, false, "V", &result); 3662 } 3663 } 3664 } 3665 } 3666 3667 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env, 3668 jarray array, jsize start, jsize len, void* buf) { 3669 CHECK_ATTACHED_THREAD_VOID(function_name); 3670 ScopedObjectAccess soa(env); 3671 ScopedCheck sc(kFlag_Default, function_name); 3672 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}}; 3673 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 3674 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 3675 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3676 switch (type) { 3677 case Primitive::kPrimBoolean: 3678 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len, 3679 reinterpret_cast<jboolean*>(buf)); 3680 break; 3681 case Primitive::kPrimByte: 3682 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len, 3683 reinterpret_cast<jbyte*>(buf)); 3684 break; 3685 case Primitive::kPrimChar: 3686 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len, 3687 reinterpret_cast<jchar*>(buf)); 3688 break; 3689 case Primitive::kPrimShort: 3690 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len, 3691 reinterpret_cast<jshort*>(buf)); 3692 break; 3693 case Primitive::kPrimInt: 3694 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len, 3695 reinterpret_cast<jint*>(buf)); 3696 break; 3697 case Primitive::kPrimLong: 3698 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len, 3699 reinterpret_cast<jlong*>(buf)); 3700 break; 3701 case Primitive::kPrimFloat: 3702 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len, 3703 reinterpret_cast<jfloat*>(buf)); 3704 break; 3705 case Primitive::kPrimDouble: 3706 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len, 3707 reinterpret_cast<jdouble*>(buf)); 3708 break; 3709 default: 3710 LOG(FATAL) << "Unexpected primitive type: " << type; 3711 } 3712 JniValueType result; 3713 result.V = nullptr; 3714 sc.Check(soa, false, "V", &result); 3715 } 3716 } 3717 3718 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env, 3719 jarray array, jsize start, jsize len, const void* buf) { 3720 CHECK_ATTACHED_THREAD_VOID(function_name); 3721 ScopedObjectAccess soa(env); 3722 ScopedCheck sc(kFlag_Default, function_name); 3723 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}}; 3724 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 3725 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 3726 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3727 switch (type) { 3728 case Primitive::kPrimBoolean: 3729 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len, 3730 reinterpret_cast<const jboolean*>(buf)); 3731 break; 3732 case Primitive::kPrimByte: 3733 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len, 3734 reinterpret_cast<const jbyte*>(buf)); 3735 break; 3736 case Primitive::kPrimChar: 3737 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len, 3738 reinterpret_cast<const jchar*>(buf)); 3739 break; 3740 case Primitive::kPrimShort: 3741 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len, 3742 reinterpret_cast<const jshort*>(buf)); 3743 break; 3744 case Primitive::kPrimInt: 3745 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len, 3746 reinterpret_cast<const jint*>(buf)); 3747 break; 3748 case Primitive::kPrimLong: 3749 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len, 3750 reinterpret_cast<const jlong*>(buf)); 3751 break; 3752 case Primitive::kPrimFloat: 3753 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len, 3754 reinterpret_cast<const jfloat*>(buf)); 3755 break; 3756 case Primitive::kPrimDouble: 3757 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len, 3758 reinterpret_cast<const jdouble*>(buf)); 3759 break; 3760 default: 3761 LOG(FATAL) << "Unexpected primitive type: " << type; 3762 } 3763 JniValueType result; 3764 result.V = nullptr; 3765 sc.Check(soa, false, "V", &result); 3766 } 3767 } 3768 }; 3769 3770 const JNINativeInterface gCheckNativeInterface = { 3771 nullptr, // reserved0. 3772 nullptr, // reserved1. 3773 nullptr, // reserved2. 3774 nullptr, // reserved3. 3775 CheckJNI::GetVersion, 3776 CheckJNI::DefineClass, 3777 CheckJNI::FindClass, 3778 CheckJNI::FromReflectedMethod, 3779 CheckJNI::FromReflectedField, 3780 CheckJNI::ToReflectedMethod, 3781 CheckJNI::GetSuperclass, 3782 CheckJNI::IsAssignableFrom, 3783 CheckJNI::ToReflectedField, 3784 CheckJNI::Throw, 3785 CheckJNI::ThrowNew, 3786 CheckJNI::ExceptionOccurred, 3787 CheckJNI::ExceptionDescribe, 3788 CheckJNI::ExceptionClear, 3789 CheckJNI::FatalError, 3790 CheckJNI::PushLocalFrame, 3791 CheckJNI::PopLocalFrame, 3792 CheckJNI::NewGlobalRef, 3793 CheckJNI::DeleteGlobalRef, 3794 CheckJNI::DeleteLocalRef, 3795 CheckJNI::IsSameObject, 3796 CheckJNI::NewLocalRef, 3797 CheckJNI::EnsureLocalCapacity, 3798 CheckJNI::AllocObject, 3799 CheckJNI::NewObject, 3800 CheckJNI::NewObjectV, 3801 CheckJNI::NewObjectA, 3802 CheckJNI::GetObjectClass, 3803 CheckJNI::IsInstanceOf, 3804 CheckJNI::GetMethodID, 3805 CheckJNI::CallObjectMethod, 3806 CheckJNI::CallObjectMethodV, 3807 CheckJNI::CallObjectMethodA, 3808 CheckJNI::CallBooleanMethod, 3809 CheckJNI::CallBooleanMethodV, 3810 CheckJNI::CallBooleanMethodA, 3811 CheckJNI::CallByteMethod, 3812 CheckJNI::CallByteMethodV, 3813 CheckJNI::CallByteMethodA, 3814 CheckJNI::CallCharMethod, 3815 CheckJNI::CallCharMethodV, 3816 CheckJNI::CallCharMethodA, 3817 CheckJNI::CallShortMethod, 3818 CheckJNI::CallShortMethodV, 3819 CheckJNI::CallShortMethodA, 3820 CheckJNI::CallIntMethod, 3821 CheckJNI::CallIntMethodV, 3822 CheckJNI::CallIntMethodA, 3823 CheckJNI::CallLongMethod, 3824 CheckJNI::CallLongMethodV, 3825 CheckJNI::CallLongMethodA, 3826 CheckJNI::CallFloatMethod, 3827 CheckJNI::CallFloatMethodV, 3828 CheckJNI::CallFloatMethodA, 3829 CheckJNI::CallDoubleMethod, 3830 CheckJNI::CallDoubleMethodV, 3831 CheckJNI::CallDoubleMethodA, 3832 CheckJNI::CallVoidMethod, 3833 CheckJNI::CallVoidMethodV, 3834 CheckJNI::CallVoidMethodA, 3835 CheckJNI::CallNonvirtualObjectMethod, 3836 CheckJNI::CallNonvirtualObjectMethodV, 3837 CheckJNI::CallNonvirtualObjectMethodA, 3838 CheckJNI::CallNonvirtualBooleanMethod, 3839 CheckJNI::CallNonvirtualBooleanMethodV, 3840 CheckJNI::CallNonvirtualBooleanMethodA, 3841 CheckJNI::CallNonvirtualByteMethod, 3842 CheckJNI::CallNonvirtualByteMethodV, 3843 CheckJNI::CallNonvirtualByteMethodA, 3844 CheckJNI::CallNonvirtualCharMethod, 3845 CheckJNI::CallNonvirtualCharMethodV, 3846 CheckJNI::CallNonvirtualCharMethodA, 3847 CheckJNI::CallNonvirtualShortMethod, 3848 CheckJNI::CallNonvirtualShortMethodV, 3849 CheckJNI::CallNonvirtualShortMethodA, 3850 CheckJNI::CallNonvirtualIntMethod, 3851 CheckJNI::CallNonvirtualIntMethodV, 3852 CheckJNI::CallNonvirtualIntMethodA, 3853 CheckJNI::CallNonvirtualLongMethod, 3854 CheckJNI::CallNonvirtualLongMethodV, 3855 CheckJNI::CallNonvirtualLongMethodA, 3856 CheckJNI::CallNonvirtualFloatMethod, 3857 CheckJNI::CallNonvirtualFloatMethodV, 3858 CheckJNI::CallNonvirtualFloatMethodA, 3859 CheckJNI::CallNonvirtualDoubleMethod, 3860 CheckJNI::CallNonvirtualDoubleMethodV, 3861 CheckJNI::CallNonvirtualDoubleMethodA, 3862 CheckJNI::CallNonvirtualVoidMethod, 3863 CheckJNI::CallNonvirtualVoidMethodV, 3864 CheckJNI::CallNonvirtualVoidMethodA, 3865 CheckJNI::GetFieldID, 3866 CheckJNI::GetObjectField, 3867 CheckJNI::GetBooleanField, 3868 CheckJNI::GetByteField, 3869 CheckJNI::GetCharField, 3870 CheckJNI::GetShortField, 3871 CheckJNI::GetIntField, 3872 CheckJNI::GetLongField, 3873 CheckJNI::GetFloatField, 3874 CheckJNI::GetDoubleField, 3875 CheckJNI::SetObjectField, 3876 CheckJNI::SetBooleanField, 3877 CheckJNI::SetByteField, 3878 CheckJNI::SetCharField, 3879 CheckJNI::SetShortField, 3880 CheckJNI::SetIntField, 3881 CheckJNI::SetLongField, 3882 CheckJNI::SetFloatField, 3883 CheckJNI::SetDoubleField, 3884 CheckJNI::GetStaticMethodID, 3885 CheckJNI::CallStaticObjectMethod, 3886 CheckJNI::CallStaticObjectMethodV, 3887 CheckJNI::CallStaticObjectMethodA, 3888 CheckJNI::CallStaticBooleanMethod, 3889 CheckJNI::CallStaticBooleanMethodV, 3890 CheckJNI::CallStaticBooleanMethodA, 3891 CheckJNI::CallStaticByteMethod, 3892 CheckJNI::CallStaticByteMethodV, 3893 CheckJNI::CallStaticByteMethodA, 3894 CheckJNI::CallStaticCharMethod, 3895 CheckJNI::CallStaticCharMethodV, 3896 CheckJNI::CallStaticCharMethodA, 3897 CheckJNI::CallStaticShortMethod, 3898 CheckJNI::CallStaticShortMethodV, 3899 CheckJNI::CallStaticShortMethodA, 3900 CheckJNI::CallStaticIntMethod, 3901 CheckJNI::CallStaticIntMethodV, 3902 CheckJNI::CallStaticIntMethodA, 3903 CheckJNI::CallStaticLongMethod, 3904 CheckJNI::CallStaticLongMethodV, 3905 CheckJNI::CallStaticLongMethodA, 3906 CheckJNI::CallStaticFloatMethod, 3907 CheckJNI::CallStaticFloatMethodV, 3908 CheckJNI::CallStaticFloatMethodA, 3909 CheckJNI::CallStaticDoubleMethod, 3910 CheckJNI::CallStaticDoubleMethodV, 3911 CheckJNI::CallStaticDoubleMethodA, 3912 CheckJNI::CallStaticVoidMethod, 3913 CheckJNI::CallStaticVoidMethodV, 3914 CheckJNI::CallStaticVoidMethodA, 3915 CheckJNI::GetStaticFieldID, 3916 CheckJNI::GetStaticObjectField, 3917 CheckJNI::GetStaticBooleanField, 3918 CheckJNI::GetStaticByteField, 3919 CheckJNI::GetStaticCharField, 3920 CheckJNI::GetStaticShortField, 3921 CheckJNI::GetStaticIntField, 3922 CheckJNI::GetStaticLongField, 3923 CheckJNI::GetStaticFloatField, 3924 CheckJNI::GetStaticDoubleField, 3925 CheckJNI::SetStaticObjectField, 3926 CheckJNI::SetStaticBooleanField, 3927 CheckJNI::SetStaticByteField, 3928 CheckJNI::SetStaticCharField, 3929 CheckJNI::SetStaticShortField, 3930 CheckJNI::SetStaticIntField, 3931 CheckJNI::SetStaticLongField, 3932 CheckJNI::SetStaticFloatField, 3933 CheckJNI::SetStaticDoubleField, 3934 CheckJNI::NewString, 3935 CheckJNI::GetStringLength, 3936 CheckJNI::GetStringChars, 3937 CheckJNI::ReleaseStringChars, 3938 CheckJNI::NewStringUTF, 3939 CheckJNI::GetStringUTFLength, 3940 CheckJNI::GetStringUTFChars, 3941 CheckJNI::ReleaseStringUTFChars, 3942 CheckJNI::GetArrayLength, 3943 CheckJNI::NewObjectArray, 3944 CheckJNI::GetObjectArrayElement, 3945 CheckJNI::SetObjectArrayElement, 3946 CheckJNI::NewBooleanArray, 3947 CheckJNI::NewByteArray, 3948 CheckJNI::NewCharArray, 3949 CheckJNI::NewShortArray, 3950 CheckJNI::NewIntArray, 3951 CheckJNI::NewLongArray, 3952 CheckJNI::NewFloatArray, 3953 CheckJNI::NewDoubleArray, 3954 CheckJNI::GetBooleanArrayElements, 3955 CheckJNI::GetByteArrayElements, 3956 CheckJNI::GetCharArrayElements, 3957 CheckJNI::GetShortArrayElements, 3958 CheckJNI::GetIntArrayElements, 3959 CheckJNI::GetLongArrayElements, 3960 CheckJNI::GetFloatArrayElements, 3961 CheckJNI::GetDoubleArrayElements, 3962 CheckJNI::ReleaseBooleanArrayElements, 3963 CheckJNI::ReleaseByteArrayElements, 3964 CheckJNI::ReleaseCharArrayElements, 3965 CheckJNI::ReleaseShortArrayElements, 3966 CheckJNI::ReleaseIntArrayElements, 3967 CheckJNI::ReleaseLongArrayElements, 3968 CheckJNI::ReleaseFloatArrayElements, 3969 CheckJNI::ReleaseDoubleArrayElements, 3970 CheckJNI::GetBooleanArrayRegion, 3971 CheckJNI::GetByteArrayRegion, 3972 CheckJNI::GetCharArrayRegion, 3973 CheckJNI::GetShortArrayRegion, 3974 CheckJNI::GetIntArrayRegion, 3975 CheckJNI::GetLongArrayRegion, 3976 CheckJNI::GetFloatArrayRegion, 3977 CheckJNI::GetDoubleArrayRegion, 3978 CheckJNI::SetBooleanArrayRegion, 3979 CheckJNI::SetByteArrayRegion, 3980 CheckJNI::SetCharArrayRegion, 3981 CheckJNI::SetShortArrayRegion, 3982 CheckJNI::SetIntArrayRegion, 3983 CheckJNI::SetLongArrayRegion, 3984 CheckJNI::SetFloatArrayRegion, 3985 CheckJNI::SetDoubleArrayRegion, 3986 CheckJNI::RegisterNatives, 3987 CheckJNI::UnregisterNatives, 3988 CheckJNI::MonitorEnter, 3989 CheckJNI::MonitorExit, 3990 CheckJNI::GetJavaVM, 3991 CheckJNI::GetStringRegion, 3992 CheckJNI::GetStringUTFRegion, 3993 CheckJNI::GetPrimitiveArrayCritical, 3994 CheckJNI::ReleasePrimitiveArrayCritical, 3995 CheckJNI::GetStringCritical, 3996 CheckJNI::ReleaseStringCritical, 3997 CheckJNI::NewWeakGlobalRef, 3998 CheckJNI::DeleteWeakGlobalRef, 3999 CheckJNI::ExceptionCheck, 4000 CheckJNI::NewDirectByteBuffer, 4001 CheckJNI::GetDirectBufferAddress, 4002 CheckJNI::GetDirectBufferCapacity, 4003 CheckJNI::GetObjectRefType, 4004 }; 4005 4006 class CheckJII { 4007 public: 4008 static jint DestroyJavaVM(JavaVM* vm) { 4009 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false); 4010 JniValueType args[1] = {{.v = vm}}; 4011 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args); 4012 JniValueType result; 4013 result.i = BaseVm(vm)->DestroyJavaVM(vm); 4014 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime, 4015 // which will delete the JavaVMExt. 4016 sc.CheckNonHeap(nullptr, false, "i", &result); 4017 return result.i; 4018 } 4019 4020 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 4021 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 4022 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}}; 4023 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args); 4024 JniValueType result; 4025 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args); 4026 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 4027 return result.i; 4028 } 4029 4030 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 4031 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 4032 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}}; 4033 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args); 4034 JniValueType result; 4035 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args); 4036 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 4037 return result.i; 4038 } 4039 4040 static jint DetachCurrentThread(JavaVM* vm) { 4041 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 4042 JniValueType args[1] = {{.v = vm}}; 4043 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args); 4044 JniValueType result; 4045 result.i = BaseVm(vm)->DetachCurrentThread(vm); 4046 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 4047 return result.i; 4048 } 4049 4050 static jint GetEnv(JavaVM* vm, void** p_env, jint version) { 4051 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 4052 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}}; 4053 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args); 4054 JniValueType result; 4055 result.i = BaseVm(vm)->GetEnv(vm, p_env, version); 4056 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 4057 return result.i; 4058 } 4059 4060 private: 4061 static const JNIInvokeInterface* BaseVm(JavaVM* vm) { 4062 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions(); 4063 } 4064 }; 4065 4066 const JNIInvokeInterface gCheckInvokeInterface = { 4067 nullptr, // reserved0 4068 nullptr, // reserved1 4069 nullptr, // reserved2 4070 CheckJII::DestroyJavaVM, 4071 CheckJII::AttachCurrentThread, 4072 CheckJII::DetachCurrentThread, 4073 CheckJII::GetEnv, 4074 CheckJII::AttachCurrentThreadAsDaemon 4075 }; 4076 4077 } // anonymous namespace 4078 4079 const JNINativeInterface* GetCheckJniNativeInterface() { 4080 return &gCheckNativeInterface; 4081 } 4082 4083 const JNIInvokeInterface* GetCheckJniInvokeInterface() { 4084 return &gCheckInvokeInterface; 4085 } 4086 4087 } // namespace art 4088