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