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