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