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