1 /*
   2  * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "classfile/javaClasses.inline.hpp"
  26 #include "classfile/vmClasses.hpp"
  27 #include "classfile/vmSymbols.hpp"
  28 #include "jni.h"
  29 #include "jvm.h"
  30 #include "logging/log.hpp"
  31 #include "logging/logTag.hpp"
  32 #include "memory/allocation.inline.hpp"
  33 #include "memory/guardedMemory.hpp"
  34 #include "oops/instanceKlass.hpp"
  35 #include "oops/oop.inline.hpp"
  36 #include "oops/symbol.hpp"
  37 #include "prims/jniCheck.hpp"
  38 #include "prims/jvm_misc.hpp"
  39 #include "runtime/fieldDescriptor.inline.hpp"
  40 #include "runtime/handles.inline.hpp"
  41 #include "runtime/interfaceSupport.inline.hpp"
  42 #include "runtime/javaThread.hpp"
  43 #include "runtime/jfieldIDWorkaround.hpp"
  44 #include "runtime/jniHandles.inline.hpp"
  45 #include "utilities/formatBuffer.hpp"
  46 #include "utilities/utf8.hpp"
  47 
  48 // Heap objects are allowed to be directly referenced only in VM code,
  49 // not in native code.
  50 
  51 #define ASSERT_OOPS_ALLOWED                                          \
  52     assert(JavaThread::current()->thread_state() == _thread_in_vm,   \
  53            "jniCheck examining oops in bad state.")
  54 
  55 
  56 // Execute the given block of source code with the thread in VM state.
  57 // To do this, transition from the NATIVE state to the VM state, execute
  58 // the code, and transition back.  The ThreadInVMfromNative constructor
  59 // performs the transition to VM state, its destructor restores the
  60 // NATIVE state.
  61 
  62 #define IN_VM(source_code)   {                                         \
  63     {                                                                  \
  64       ThreadInVMfromNative __tiv(thr);                                 \
  65       source_code                                                      \
  66     }                                                                  \
  67   }
  68 
  69 
  70 /*
  71  * DECLARATIONS
  72  */
  73 
  74 static struct JNINativeInterface_ * unchecked_jni_NativeInterface;
  75 
  76 
  77 /*
  78  * MACRO DEFINITIONS
  79  */
  80 
  81 // All JNI checked functions here use JNI_ENTRY_CHECKED() instead of the
  82 // QUICK_ENTRY or LEAF variants found in jni.cpp.  This allows handles
  83 // to be created if a fatal error should occur.
  84 
  85 // Check for thread not attached to VM;  need to catch this before
  86 // assertions in the wrapper routines might fire
  87 
  88 // Check for env being the one value appropriate for this thread.
  89 
  90 #define JNI_ENTRY_CHECKED(result_type, header)                           \
  91 extern "C" {                                                             \
  92   result_type JNICALL header {                                           \
  93     Thread* cur = Thread::current_or_null();                             \
  94     if (cur == nullptr || !cur->is_Java_thread()) {                      \
  95       tty->print_cr("%s", fatal_using_jnienv_in_nonjava);                \
  96       os::abort(true);                                                   \
  97     }                                                                    \
  98     JavaThread* thr = JavaThread::cast(cur);                             \
  99     JNIEnv* xenv = thr->jni_environment();                               \
 100     if (env != xenv) {                                                   \
 101       NativeReportJNIFatalError(thr, warn_wrong_jnienv);                 \
 102     }                                                                    \
 103     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thr));               \
 104     VM_ENTRY_BASE(result_type, header, thr)
 105 
 106 
 107 #define UNCHECKED() (unchecked_jni_NativeInterface)
 108 
 109 static const char * warn_wrong_jnienv = "Using JNIEnv in the wrong thread";
 110 static const char * warn_bad_class_descriptor1 = "JNI FindClass received a bad class descriptor \"";
 111 static const char * warn_bad_class_descriptor2 = "\".  A correct class descriptor " \
 112   "has no leading \"L\" or trailing \";\".  Incorrect descriptors will not be accepted in future releases.";
 113 static const char * fatal_using_jnienv_in_nonjava = "FATAL ERROR in native method: Using JNIEnv in non-Java thread";
 114 static const char * warn_other_function_in_critical = "Warning: Calling other JNI functions in the scope of " \
 115   "Get/ReleasePrimitiveArrayCritical or Get/ReleaseStringCritical";
 116 static const char * fatal_bad_ref_to_jni = "Bad global or local ref passed to JNI";
 117 static const char * fatal_received_null_class = "JNI received a null class";
 118 static const char * fatal_class_not_a_class = "JNI received a class argument that is not a class";
 119 static const char * fatal_class_not_a_throwable_class = "JNI Throw or ThrowNew received a class argument that is not a Throwable or Throwable subclass";
 120 static const char * fatal_wrong_class_or_method = "Wrong object class or methodID passed to JNI call";
 121 static const char * fatal_non_weak_method = "non-weak methodID passed to JNI call";
 122 static const char * fatal_unknown_array_object = "Unknown array object passed to JNI array operations";
 123 static const char * fatal_object_array_expected = "Object array expected but not received for JNI array operation";
 124 static const char * fatal_prim_type_array_expected = "Primitive type array expected but not received for JNI array operation";
 125 static const char * fatal_non_array  = "Non-array passed to JNI array operations";
 126 static const char * fatal_element_type_mismatch = "Array element type mismatch in JNI";
 127 static const char * fatal_should_be_static = "Non-static field ID passed to JNI";
 128 static const char * fatal_wrong_static_field = "Wrong static field ID passed to JNI";
 129 static const char * fatal_static_field_not_found = "Static field not found in JNI get/set field operations";
 130 static const char * fatal_static_field_mismatch = "Field type (static) mismatch in JNI get/set field operations";
 131 static const char * fatal_should_be_nonstatic = "Static field ID passed to JNI";
 132 static const char * fatal_null_object = "Null object passed to JNI";
 133 static const char * fatal_wrong_field = "Wrong field ID passed to JNI";
 134 static const char * fatal_instance_field_not_found = "Instance field not found in JNI get/set field operations";
 135 static const char * fatal_instance_field_mismatch = "Field type (instance) mismatch in JNI get/set field operations";
 136 static const char * fatal_non_string = "JNI string operation received a non-string";
 137 static const char * fatal_non_utf8_class_name1 = "JNI class name is not a valid UTF8 string \"";
 138 static const char * fatal_non_utf8_class_name2 = "\"";
 139 
 140 
 141 // When in VM state:
 142 static void ReportJNIWarning(JavaThread* thr, const char *msg) {
 143   tty->print_cr("WARNING in native method: %s", msg);
 144   thr->print_jni_stack();
 145 }
 146 
 147 // When in NATIVE state:
 148 static void NativeReportJNIFatalError(JavaThread* thr, const char *msg) {
 149   IN_VM(
 150     ReportJNIFatalError(thr, msg);
 151   )
 152 }
 153 
 154 static void NativeReportJNIWarning(JavaThread* thr, const char *msg) {
 155   IN_VM(
 156     ReportJNIWarning(thr, msg);
 157   )
 158 }
 159 
 160 
 161 
 162 
 163 /*
 164  * SUPPORT FUNCTIONS
 165  */
 166 
 167 /**
 168  * Check whether or not a programmer has actually checked for exceptions. According
 169  * to the JNI Specification ("jni/spec/design.html#java_exceptions"):
 170  *
 171  * There are two cases where the programmer needs to check for exceptions without
 172  * being able to first check an error code:
 173  *
 174  * - The JNI functions that invoke a Java method return the result of the Java method.
 175  * The programmer must call ExceptionOccurred() to check for possible exceptions
 176  * that occurred during the execution of the Java method.
 177  *
 178  * - Some of the JNI array access functions do not return an error code, but may
 179  * throw an ArrayIndexOutOfBoundsException or ArrayStoreException.
 180  *
 181  * In all other cases, a non-error return value guarantees that no exceptions have been thrown.
 182  *
 183  * Programmers often defend against ArrayIndexOutOfBoundsException, so warning
 184  * for these functions would be pedantic.
 185  */
 186 static inline void
 187 check_pending_exception(JavaThread* thr) {
 188   if (thr->has_pending_exception()) {
 189     NativeReportJNIWarning(thr, "JNI call made with exception pending");
 190   }
 191   if (thr->is_pending_jni_exception_check()) {
 192     IN_VM(
 193       tty->print_cr("WARNING in native method: JNI call made without checking exceptions when required to from %s",
 194         thr->get_pending_jni_exception_check());
 195       thr->print_jni_stack();
 196     )
 197     thr->clear_pending_jni_exception_check(); // Just complain once
 198   }
 199 }
 200 
 201 static inline void
 202 functionEnterCritical(JavaThread* thr)
 203 {
 204   check_pending_exception(thr);
 205 }
 206 
 207 static inline void
 208 functionEnterCriticalExceptionAllowed(JavaThread* thr)
 209 {
 210 }
 211 
 212 static inline void
 213 functionEnter(JavaThread* thr)
 214 {
 215   if (thr->in_critical()) {
 216     tty->print_cr("%s", warn_other_function_in_critical);
 217   }
 218   check_pending_exception(thr);
 219 }
 220 
 221 static inline void
 222 functionEnterExceptionAllowed(JavaThread* thr)
 223 {
 224   if (thr->in_critical()) {
 225     tty->print_cr("%s", warn_other_function_in_critical);
 226   }
 227 }
 228 
 229 static inline void
 230 functionExit(JavaThread* thr)
 231 {
 232   // No checks at this time
 233 }
 234 
 235 static inline void
 236 checkStaticFieldID(JavaThread* thr, jfieldID fid, jclass cls, int ftype, bool setter)
 237 {
 238   fieldDescriptor fd;
 239 
 240   /* make sure it is a static field */
 241   if (!jfieldIDWorkaround::is_static_jfieldID(fid))
 242     ReportJNIFatalError(thr, fatal_should_be_static);
 243 
 244   /* validate the class being passed */
 245   ASSERT_OOPS_ALLOWED;
 246   Klass* k_oop = jniCheck::validate_class(thr, cls, false);
 247 
 248   /* check for proper subclass hierarchy */
 249   JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fid);
 250   Klass* f_oop = id->holder();
 251   if (!k_oop->is_subtype_of(f_oop))
 252     ReportJNIFatalError(thr, fatal_wrong_static_field);
 253 
 254   /* check for proper field type */
 255   if (!id->find_local_field(&fd))
 256     ReportJNIFatalError(thr, fatal_static_field_not_found);
 257   if ((fd.field_type() != ftype) &&
 258       !(fd.field_type() == T_ARRAY && ftype == T_OBJECT)) {
 259     ReportJNIFatalError(thr, fatal_static_field_mismatch);
 260   }
 261 
 262   /* check if setting a final field */
 263   if (setter && fd.is_final() && !fd.is_mutable_static_final()) {
 264     ResourceMark rm(thr);
 265     stringStream ss;
 266     ss.print("SetStatic<Type>Field called to mutate final static field %s.%s", k_oop->external_name(), fd.name()->as_C_string());
 267     ReportJNIWarning(thr, ss.as_string());
 268   }
 269 }
 270 
 271 static inline void
 272 checkInstanceFieldID(JavaThread* thr, jfieldID fid, jobject obj, int ftype, bool setter)
 273 {
 274   fieldDescriptor fd;
 275 
 276   /* make sure it is an instance field */
 277   if (jfieldIDWorkaround::is_static_jfieldID(fid))
 278     ReportJNIFatalError(thr, fatal_should_be_nonstatic);
 279 
 280   /* validate the object being passed and then get its class */
 281   ASSERT_OOPS_ALLOWED;
 282   oop oopObj = jniCheck::validate_object(thr, obj);
 283   if (oopObj == nullptr) {
 284     ReportJNIFatalError(thr, fatal_null_object);
 285   }
 286   Klass* k_oop = oopObj->klass();
 287 
 288   if (!jfieldIDWorkaround::is_valid_jfieldID(k_oop, fid)) {
 289     ReportJNIFatalError(thr, fatal_wrong_field);
 290   }
 291 
 292   /* make sure the field exists */
 293   int offset = jfieldIDWorkaround::from_instance_jfieldID(k_oop, fid);
 294   if (!InstanceKlass::cast(k_oop)->contains_field_offset(offset))
 295     ReportJNIFatalError(thr, fatal_wrong_field);
 296 
 297   /* check for proper field type */
 298   if (!InstanceKlass::cast(k_oop)->find_field_from_offset(offset, false, &fd))
 299     ReportJNIFatalError(thr, fatal_instance_field_not_found);
 300 
 301   if ((fd.field_type() != ftype) &&
 302       !(fd.field_type() == T_ARRAY && ftype == T_OBJECT)) {
 303     ReportJNIFatalError(thr, fatal_instance_field_mismatch);
 304   }
 305 
 306   /* check if setting a final field */
 307   if (setter && fd.is_final()) {
 308     ResourceMark rm(thr);
 309     stringStream ss;
 310     ss.print("Set<Type>Field called to mutate final instance field %s.%s", k_oop->external_name(), fd.name()->as_C_string());
 311     ReportJNIWarning(thr, ss.as_string());
 312   }
 313 }
 314 
 315 static inline void
 316 checkString(JavaThread* thr, jstring js)
 317 {
 318   ASSERT_OOPS_ALLOWED;
 319   oop s = jniCheck::validate_object(thr, js);
 320   if ((s == nullptr) || !java_lang_String::is_instance(s))
 321     ReportJNIFatalError(thr, fatal_non_string);
 322 }
 323 
 324 static inline arrayOop
 325 check_is_array(JavaThread* thr, jarray jArray)
 326 {
 327   ASSERT_OOPS_ALLOWED;
 328   arrayOop aOop;
 329 
 330   aOop = (arrayOop)jniCheck::validate_object(thr, jArray);
 331   if (aOop == nullptr || !aOop->is_array()) {
 332     ReportJNIFatalError(thr, fatal_non_array);
 333   }
 334   return aOop;
 335 }
 336 
 337 static inline arrayOop
 338 check_is_primitive_array(JavaThread* thr, jarray jArray) {
 339   arrayOop aOop = check_is_array(thr, jArray);
 340 
 341   if (!aOop->is_typeArray()) {
 342      ReportJNIFatalError(thr, fatal_prim_type_array_expected);
 343   }
 344   return aOop;
 345 }
 346 
 347 static inline void
 348 check_primitive_array_type(JavaThread* thr, jarray jArray, BasicType elementType)
 349 {
 350   BasicType array_type;
 351   arrayOop aOop;
 352 
 353   aOop = check_is_primitive_array(thr, jArray);
 354   array_type = TypeArrayKlass::cast(aOop->klass())->element_type();
 355   if (array_type != elementType) {
 356     ReportJNIFatalError(thr, fatal_element_type_mismatch);
 357   }
 358 }
 359 
 360 static inline void
 361 check_is_obj_array(JavaThread* thr, jarray jArray) {
 362   arrayOop aOop = check_is_array(thr, jArray);
 363   if (!aOop->is_objArray()) {
 364     ReportJNIFatalError(thr, fatal_object_array_expected);
 365   }
 366 }
 367 
 368 // Arbitrary (but well-known) tag for GetStringChars
 369 const void* STRING_TAG = (void*)0x47114711;
 370 
 371 // Arbitrary (but well-known) tag for GetStringUTFChars
 372 const void* STRING_UTF_TAG = (void*) 0x48124812;
 373 
 374 // Arbitrary (but well-known) tag for GetPrimitiveArrayCritical
 375 const void* CRITICAL_TAG = (void*)0x49134913;
 376 
 377 /*
 378  * Copy and wrap array elements for bounds checking.
 379  * Remember the original elements (GuardedMemory::get_tag())
 380  */
 381 static void* check_jni_wrap_copy_array(JavaThread* thr, jarray array,
 382                                        void* orig_elements, jboolean is_critical = JNI_FALSE) {
 383   void* result;
 384   IN_VM(
 385     oop a = JNIHandles::resolve_non_null(array);
 386     size_t len = arrayOop(a)->length() <<
 387         TypeArrayKlass::cast(a->klass())->log2_element_size();
 388     result = GuardedMemory::wrap_copy(orig_elements, len, orig_elements, is_critical ? CRITICAL_TAG : nullptr);
 389   )
 390   return result;
 391 }
 392 
 393 static void* check_wrapped_array(JavaThread* thr, const char* fn_name,
 394                                  void* obj, void* carray, size_t* rsz, jboolean is_critical) {
 395   if (carray == nullptr) {
 396     tty->print_cr("%s: elements vector null" PTR_FORMAT, fn_name, p2i(obj));
 397     NativeReportJNIFatalError(thr, "Elements vector null");
 398   }
 399   GuardedMemory guarded(carray);
 400   void* orig_result = guarded.get_tag();
 401   if (!guarded.verify_guards()) {
 402     tty->print_cr("%s: release array failed bounds check, incorrect pointer returned ? array: "
 403                   PTR_FORMAT " carray: " PTR_FORMAT, fn_name, p2i(obj), p2i(carray));
 404     DEBUG_ONLY(guarded.print_on(tty);) // This may crash.
 405     NativeReportJNIFatalError(thr, err_msg("%s: failed bounds check", fn_name));
 406   }
 407   if (orig_result == nullptr) {
 408     tty->print_cr("%s: unrecognized elements. array: " PTR_FORMAT " carray: " PTR_FORMAT,
 409                   fn_name, p2i(obj), p2i(carray));
 410     DEBUG_ONLY(guarded.print_on(tty);) // This may crash.
 411     NativeReportJNIFatalError(thr, err_msg("%s: unrecognized elements", fn_name));
 412   }
 413   if (orig_result == STRING_TAG || orig_result == STRING_UTF_TAG) {
 414     bool was_utf = orig_result == STRING_UTF_TAG;
 415     tty->print_cr("%s: called on something allocated by %s",
 416                   fn_name, was_utf ? "GetStringUTFChars" : "GetStringChars");
 417     DEBUG_ONLY(guarded.print_on(tty);) // This may crash.
 418     NativeReportJNIFatalError(thr, err_msg("%s called on something allocated by %s",
 419                                            fn_name, was_utf ? "GetStringUTFChars" : "GetStringChars"));
 420   }
 421 
 422   if (is_critical && (guarded.get_tag2() != CRITICAL_TAG)) {
 423     tty->print_cr("%s: called on something not allocated by GetPrimitiveArrayCritical", fn_name);
 424     DEBUG_ONLY(guarded.print_on(tty);) // This may crash.
 425     NativeReportJNIFatalError(thr, err_msg("%s called on something not allocated by GetPrimitiveArrayCritical",
 426                                            fn_name));
 427   }
 428 
 429   if (!is_critical && (guarded.get_tag2() == CRITICAL_TAG)) {
 430     tty->print_cr("%s: called on something allocated by GetPrimitiveArrayCritical", fn_name);
 431     DEBUG_ONLY(guarded.print_on(tty);) // This may crash.
 432     NativeReportJNIFatalError(thr, err_msg("%s called on something allocated by GetPrimitiveArrayCritical",
 433                                            fn_name));
 434   }
 435 
 436   if (rsz != nullptr) {
 437     *rsz = guarded.get_user_size();
 438   }
 439   return orig_result;
 440 }
 441 
 442 static void* check_wrapped_array_release(JavaThread* thr, const char* fn_name,
 443                                          void* obj, void* carray, jint mode, jboolean is_critical) {
 444   size_t sz;
 445   void* orig_result = check_wrapped_array(thr, fn_name, obj, carray, &sz, is_critical);
 446   switch (mode) {
 447   case 0:
 448     memcpy(orig_result, carray, sz);
 449     GuardedMemory::free_copy(carray);
 450     break;
 451   case JNI_COMMIT:
 452     memcpy(orig_result, carray, sz);
 453     if (is_critical) {
 454       // For ReleasePrimitiveArrayCritical we must free the internal buffer
 455       // allocated through GuardedMemory.
 456       GuardedMemory::free_copy(carray);
 457     }
 458     break;
 459   case JNI_ABORT:
 460     GuardedMemory::free_copy(carray);
 461     break;
 462   default:
 463     tty->print_cr("%s: Unrecognized mode %i releasing array "
 464                   PTR_FORMAT " elements " PTR_FORMAT, fn_name, mode, p2i(obj), p2i(carray));
 465     NativeReportJNIFatalError(thr, "Unrecognized array release mode");
 466   }
 467   return orig_result;
 468 }
 469 
 470 oop jniCheck::validate_handle(JavaThread* thr, jobject obj) {
 471   if ((obj != nullptr) && (JNIHandles::handle_type(thr, obj) != JNIInvalidRefType)) {
 472     ASSERT_OOPS_ALLOWED;
 473     return JNIHandles::resolve_external_guard(obj);
 474   }
 475   ReportJNIFatalError(thr, fatal_bad_ref_to_jni);
 476   return nullptr;
 477 }
 478 
 479 
 480 Method* jniCheck::validate_jmethod_id(JavaThread* thr, jmethodID method_id) {
 481   ASSERT_OOPS_ALLOWED;
 482   // do the fast jmethodID check first
 483   Method* m = Method::checked_resolve_jmethod_id(method_id);
 484   if (m == nullptr) {
 485     ReportJNIFatalError(thr, fatal_wrong_class_or_method);
 486   }
 487   // jmethodIDs are handles in the class loader data,
 488   // but that can be expensive so check it last
 489   else if (!Method::validate_jmethod_id(method_id)) {
 490     ReportJNIFatalError(thr, fatal_non_weak_method);
 491   }
 492   return m;
 493 }
 494 
 495 
 496 oop jniCheck::validate_object(JavaThread* thr, jobject obj) {
 497   if (obj == nullptr) return nullptr;
 498   ASSERT_OOPS_ALLOWED;
 499   oop oopObj = jniCheck::validate_handle(thr, obj);
 500   if (oopObj == nullptr) {
 501     ReportJNIFatalError(thr, fatal_bad_ref_to_jni);
 502   }
 503   return oopObj;
 504 }
 505 
 506 // Warn if a class descriptor is in decorated form; class descriptors
 507 // passed to JNI findClass should not be decorated unless they are
 508 // array descriptors.
 509 void jniCheck::validate_class_descriptor(JavaThread* thr, const char* name) {
 510   if (name == nullptr) return;  // implementation accepts null so just return
 511 
 512   size_t len = strlen(name);
 513 
 514   if (len >= 2 &&
 515       name[0] == JVM_SIGNATURE_CLASS &&            // 'L'
 516       name[len-1] == JVM_SIGNATURE_ENDCLASS ) {    // ';'
 517     char msg[JVM_MAXPATHLEN];
 518     jio_snprintf(msg, JVM_MAXPATHLEN, "%s%s%s",
 519                  warn_bad_class_descriptor1, name, warn_bad_class_descriptor2);
 520     ReportJNIWarning(thr, msg);
 521   }
 522 
 523   // Verify that the class name given is a valid utf8 string
 524   if (!UTF8::is_legal_utf8((const unsigned char*)name, strlen(name), false)) {
 525     char msg[JVM_MAXPATHLEN];
 526     jio_snprintf(msg, JVM_MAXPATHLEN, "%s%s%s", fatal_non_utf8_class_name1, name, fatal_non_utf8_class_name2);
 527     ReportJNIFatalError(thr, msg);
 528   }
 529 }
 530 
 531 Klass* jniCheck::validate_class(JavaThread* thr, jclass clazz, bool allow_primitive) {
 532   ASSERT_OOPS_ALLOWED;
 533   oop mirror = jniCheck::validate_handle(thr, clazz);
 534   if (mirror == nullptr) {
 535     ReportJNIFatalError(thr, fatal_received_null_class);
 536   }
 537 
 538   if (mirror->klass() != vmClasses::Class_klass()) {
 539     ReportJNIFatalError(thr, fatal_class_not_a_class);
 540   }
 541 
 542   Klass* k = java_lang_Class::as_Klass(mirror);
 543   // Make allowances for primitive classes ...
 544   if (!(k != nullptr || (allow_primitive && java_lang_Class::is_primitive(mirror)))) {
 545     ReportJNIFatalError(thr, fatal_class_not_a_class);
 546   }
 547   return k;
 548 }
 549 
 550 void jniCheck::validate_throwable_klass(JavaThread* thr, Klass* klass) {
 551   ASSERT_OOPS_ALLOWED;
 552   assert(klass != nullptr, "klass argument must have a value");
 553 
 554   if (!klass->is_instance_klass() ||
 555       !klass->is_subclass_of(vmClasses::Throwable_klass())) {
 556     ReportJNIFatalError(thr, fatal_class_not_a_throwable_class);
 557   }
 558 }
 559 
 560 void jniCheck::validate_call(JavaThread* thr, jclass clazz, jmethodID method_id, jobject obj) {
 561   ASSERT_OOPS_ALLOWED;
 562   Method* m = jniCheck::validate_jmethod_id(thr, method_id);
 563   InstanceKlass* holder = m->method_holder();
 564 
 565   if (clazz != nullptr) {
 566     Klass* k = jniCheck::validate_class(thr, clazz, false);
 567     // Check that method is in the class, must be InstanceKlass
 568     if (!InstanceKlass::cast(k)->is_subtype_of(holder)) {
 569       ReportJNIFatalError(thr, fatal_wrong_class_or_method);
 570     }
 571   }
 572 
 573   if (obj != nullptr) {
 574     oop recv = jniCheck::validate_object(thr, obj);
 575     assert(recv != nullptr, "validate_object checks that");
 576     Klass* rk = recv->klass();
 577 
 578     // Check that the object is a subtype of method holder too.
 579     if (!rk->is_subtype_of(holder)) {
 580       ReportJNIFatalError(thr, fatal_wrong_class_or_method);
 581     }
 582   }
 583 }
 584 
 585 
 586 /*
 587  * IMPLEMENTATION OF FUNCTIONS IN CHECKED TABLE
 588  */
 589 
 590 JNI_ENTRY_CHECKED(jclass,
 591   checked_jni_DefineClass(JNIEnv *env,
 592                           const char *name,
 593                           jobject loader,
 594                           const jbyte *buf,
 595                           jsize len))
 596     functionEnter(thr);
 597     IN_VM(
 598       jniCheck::validate_object(thr, loader);
 599     )
 600     jclass result = UNCHECKED()->DefineClass(env, name, loader, buf, len);
 601     functionExit(thr);
 602     return result;
 603 JNI_END
 604 
 605 JNI_ENTRY_CHECKED(jclass,
 606   checked_jni_FindClass(JNIEnv *env,
 607                         const char *name))
 608     functionEnter(thr);
 609     IN_VM(
 610       jniCheck::validate_class_descriptor(thr, name);
 611     )
 612     jclass result = UNCHECKED()->FindClass(env, name);
 613     functionExit(thr);
 614     return result;
 615 JNI_END
 616 
 617 JNI_ENTRY_CHECKED(jmethodID,
 618   checked_jni_FromReflectedMethod(JNIEnv *env,
 619                                   jobject method))
 620     functionEnter(thr);
 621     IN_VM(
 622       jniCheck::validate_object(thr, method);
 623     )
 624     jmethodID result = UNCHECKED()->FromReflectedMethod(env, method);
 625     functionExit(thr);
 626     return result;
 627 JNI_END
 628 
 629 JNI_ENTRY_CHECKED(jfieldID,
 630   checked_jni_FromReflectedField(JNIEnv *env,
 631                                  jobject field))
 632     functionEnter(thr);
 633     IN_VM(
 634       jniCheck::validate_object(thr, field);
 635     )
 636     jfieldID result = UNCHECKED()->FromReflectedField(env, field);
 637     functionExit(thr);
 638     return result;
 639 JNI_END
 640 
 641 JNI_ENTRY_CHECKED(jobject,
 642   checked_jni_ToReflectedMethod(JNIEnv *env,
 643                                 jclass cls,
 644                                 jmethodID methodID,
 645                                 jboolean isStatic))
 646     functionEnter(thr);
 647     IN_VM(
 648       jniCheck::validate_call(thr, cls, methodID);
 649     )
 650     jobject result = UNCHECKED()->ToReflectedMethod(env, cls, methodID,
 651                                                     isStatic);
 652     functionExit(thr);
 653     return result;
 654 JNI_END
 655 
 656 JNI_ENTRY_CHECKED(jclass,
 657   checked_jni_GetSuperclass(JNIEnv *env,
 658                             jclass sub))
 659     functionEnter(thr);
 660     IN_VM(
 661       jniCheck::validate_class(thr, sub, true);
 662     )
 663     jclass result = UNCHECKED()->GetSuperclass(env, sub);
 664     functionExit(thr);
 665     return result;
 666 JNI_END
 667 
 668 JNI_ENTRY_CHECKED(jboolean,
 669   checked_jni_IsAssignableFrom(JNIEnv *env,
 670                                jclass sub,
 671                                jclass sup))
 672     functionEnter(thr);
 673     IN_VM(
 674       jniCheck::validate_class(thr, sub, true);
 675       jniCheck::validate_class(thr, sup, true);
 676     )
 677     jboolean result = UNCHECKED()->IsAssignableFrom(env, sub, sup);
 678     functionExit(thr);
 679     return result;
 680 JNI_END
 681 
 682 JNI_ENTRY_CHECKED(jobject,
 683   checked_jni_ToReflectedField(JNIEnv *env,
 684                                jclass cls,
 685                                jfieldID fieldID,
 686                                jboolean isStatic))
 687     functionEnter(thr);
 688     IN_VM(
 689       jniCheck::validate_class(thr, cls, false);
 690     )
 691     jobject result = UNCHECKED()->ToReflectedField(env, cls, fieldID,
 692                                                    isStatic);
 693     functionExit(thr);
 694     return result;
 695 JNI_END
 696 
 697 JNI_ENTRY_CHECKED(jint,
 698   checked_jni_Throw(JNIEnv *env,
 699                     jthrowable obj))
 700     functionEnter(thr);
 701     IN_VM(
 702       oop oopObj = jniCheck::validate_object(thr, obj);
 703       if (oopObj == nullptr) {
 704         // Unchecked Throw tolerates a null obj, so just warn
 705         ReportJNIWarning(thr, "JNI Throw called with null throwable");
 706       } else {
 707         jniCheck::validate_throwable_klass(thr, oopObj->klass());
 708       }
 709     )
 710     jint result = UNCHECKED()->Throw(env, obj);
 711     functionExit(thr);
 712     return result;
 713 JNI_END
 714 
 715 JNI_ENTRY_CHECKED(jint,
 716   checked_jni_ThrowNew(JNIEnv *env,
 717                        jclass clazz,
 718                        const char *msg))
 719     functionEnter(thr);
 720     IN_VM(
 721       Klass* k = jniCheck::validate_class(thr, clazz, false);
 722       assert(k != nullptr, "validate_class shouldn't return null Klass*");
 723       jniCheck::validate_throwable_klass(thr, k);
 724     )
 725     jint result = UNCHECKED()->ThrowNew(env, clazz, msg);
 726     functionExit(thr);
 727     return result;
 728 JNI_END
 729 
 730 JNI_ENTRY_CHECKED(jthrowable,
 731   checked_jni_ExceptionOccurred(JNIEnv *env))
 732     thr->clear_pending_jni_exception_check();
 733     functionEnterExceptionAllowed(thr);
 734     jthrowable result = UNCHECKED()->ExceptionOccurred(env);
 735     functionExit(thr);
 736     return result;
 737 JNI_END
 738 
 739 JNI_ENTRY_CHECKED(void,
 740   checked_jni_ExceptionDescribe(JNIEnv *env))
 741     functionEnterExceptionAllowed(thr);
 742     UNCHECKED()->ExceptionDescribe(env);
 743     functionExit(thr);
 744 JNI_END
 745 
 746 JNI_ENTRY_CHECKED(void,
 747   checked_jni_ExceptionClear(JNIEnv *env))
 748     thr->clear_pending_jni_exception_check();
 749     functionEnterExceptionAllowed(thr);
 750     UNCHECKED()->ExceptionClear(env);
 751     functionExit(thr);
 752 JNI_END
 753 
 754 JNI_ENTRY_CHECKED(void,
 755   checked_jni_FatalError(JNIEnv *env,
 756                          const char *msg))
 757     thr->clear_pending_jni_exception_check();
 758     functionEnter(thr);
 759     UNCHECKED()->FatalError(env, msg);
 760     functionExit(thr);
 761 JNI_END
 762 
 763 JNI_ENTRY_CHECKED(jint,
 764   checked_jni_PushLocalFrame(JNIEnv *env,
 765                              jint capacity))
 766     functionEnterExceptionAllowed(thr);
 767     if (capacity < 0)
 768       NativeReportJNIFatalError(thr, "negative capacity");
 769     jint result = UNCHECKED()->PushLocalFrame(env, capacity);
 770     functionExit(thr);
 771     return result;
 772 JNI_END
 773 
 774 JNI_ENTRY_CHECKED(jobject,
 775   checked_jni_PopLocalFrame(JNIEnv *env,
 776                             jobject result))
 777     functionEnterExceptionAllowed(thr);
 778     jobject res = UNCHECKED()->PopLocalFrame(env, result);
 779     functionExit(thr);
 780     return res;
 781 JNI_END
 782 
 783 JNI_ENTRY_CHECKED(jobject,
 784   checked_jni_NewGlobalRef(JNIEnv *env,
 785                            jobject lobj))
 786     functionEnter(thr);
 787     IN_VM(
 788       if (lobj != nullptr) {
 789         jniCheck::validate_handle(thr, lobj);
 790       }
 791     )
 792     jobject result = UNCHECKED()->NewGlobalRef(env,lobj);
 793     functionExit(thr);
 794     return result;
 795 JNI_END
 796 
 797 JNI_ENTRY_CHECKED(void,
 798   checked_jni_DeleteGlobalRef(JNIEnv *env,
 799                               jobject gref))
 800     functionEnterExceptionAllowed(thr);
 801     IN_VM(
 802       jniCheck::validate_object(thr, gref);
 803       if (gref && !JNIHandles::is_global_handle(gref)) {
 804         ReportJNIFatalError(thr,
 805             "Invalid global JNI handle passed to DeleteGlobalRef");
 806       }
 807     )
 808     UNCHECKED()->DeleteGlobalRef(env,gref);
 809     functionExit(thr);
 810 JNI_END
 811 
 812 JNI_ENTRY_CHECKED(void,
 813   checked_jni_DeleteLocalRef(JNIEnv *env,
 814                              jobject obj))
 815     functionEnterExceptionAllowed(thr);
 816     IN_VM(
 817       jniCheck::validate_object(thr, obj);
 818       if (obj && !(JNIHandles::is_local_handle(thr, obj) ||
 819                    JNIHandles::is_frame_handle(thr, obj)))
 820         ReportJNIFatalError(thr,
 821             "Invalid local JNI handle passed to DeleteLocalRef");
 822     )
 823     UNCHECKED()->DeleteLocalRef(env, obj);
 824     functionExit(thr);
 825 JNI_END
 826 
 827 JNI_ENTRY_CHECKED(jboolean,
 828   checked_jni_IsSameObject(JNIEnv *env,
 829                            jobject obj1,
 830                            jobject obj2))
 831     functionEnterExceptionAllowed(thr);
 832     IN_VM(
 833       /* This JNI function can be used to compare weak global references
 834        * to nullptr objects. If the handles are valid, but contain nullptr,
 835        * then don't attempt to validate the object.
 836        */
 837       if (obj1 != nullptr && jniCheck::validate_handle(thr, obj1) != nullptr) {
 838         jniCheck::validate_object(thr, obj1);
 839       }
 840       if (obj2 != nullptr && jniCheck::validate_handle(thr, obj2) != nullptr) {
 841         jniCheck::validate_object(thr, obj2);
 842       }
 843     )
 844     jboolean result = UNCHECKED()->IsSameObject(env,obj1,obj2);
 845     functionExit(thr);
 846     return result;
 847 JNI_END
 848 
 849 JNI_ENTRY_CHECKED(jobject,
 850   checked_jni_NewLocalRef(JNIEnv *env,
 851                           jobject ref))
 852     functionEnter(thr);
 853     IN_VM(
 854       if (ref != nullptr) {
 855         jniCheck::validate_handle(thr, ref);
 856       }
 857     )
 858     jobject result = UNCHECKED()->NewLocalRef(env, ref);
 859     functionExit(thr);
 860     return result;
 861 JNI_END
 862 
 863 JNI_ENTRY_CHECKED(jint,
 864   checked_jni_EnsureLocalCapacity(JNIEnv *env,
 865                                   jint capacity))
 866     functionEnter(thr);
 867     if (capacity < 0) {
 868       NativeReportJNIFatalError(thr, "negative capacity");
 869     }
 870     jint result = UNCHECKED()->EnsureLocalCapacity(env, capacity);
 871     functionExit(thr);
 872     return result;
 873 JNI_END
 874 
 875 JNI_ENTRY_CHECKED(jobject,
 876   checked_jni_AllocObject(JNIEnv *env,
 877                           jclass clazz))
 878     functionEnter(thr);
 879     IN_VM(
 880       jniCheck::validate_class(thr, clazz, false);
 881     )
 882     jobject result = UNCHECKED()->AllocObject(env,clazz);
 883     functionExit(thr);
 884     return result;
 885 JNI_END
 886 
 887 JNI_ENTRY_CHECKED(jobject,
 888   checked_jni_NewObject(JNIEnv *env,
 889                         jclass clazz,
 890                         jmethodID methodID,
 891                         ...))
 892     functionEnter(thr);
 893     va_list args;
 894     IN_VM(
 895       jniCheck::validate_call(thr, clazz, methodID);
 896     )
 897     va_start(args, methodID);
 898     jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args);
 899     va_end(args);
 900     functionExit(thr);
 901     return result;
 902 JNI_END
 903 
 904 JNI_ENTRY_CHECKED(jobject,
 905   checked_jni_NewObjectV(JNIEnv *env,
 906                          jclass clazz,
 907                          jmethodID methodID,
 908                          va_list args))
 909     functionEnter(thr);
 910     IN_VM(
 911       jniCheck::validate_call(thr, clazz, methodID);
 912     )
 913     jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args);
 914     functionExit(thr);
 915     return result;
 916 JNI_END
 917 
 918 JNI_ENTRY_CHECKED(jobject,
 919   checked_jni_NewObjectA(JNIEnv *env,
 920                          jclass clazz,
 921                          jmethodID methodID,
 922                          const jvalue *args))
 923     functionEnter(thr);
 924     IN_VM(
 925       jniCheck::validate_call(thr, clazz, methodID);
 926     )
 927     jobject result = UNCHECKED()->NewObjectA(env,clazz,methodID,args);
 928     functionExit(thr);
 929     return result;
 930 JNI_END
 931 
 932 JNI_ENTRY_CHECKED(jclass,
 933   checked_jni_GetObjectClass(JNIEnv *env,
 934                              jobject obj))
 935     functionEnter(thr);
 936     IN_VM(
 937       jniCheck::validate_object(thr, obj);
 938     )
 939     jclass result = UNCHECKED()->GetObjectClass(env,obj);
 940     functionExit(thr);
 941     return result;
 942 JNI_END
 943 
 944 JNI_ENTRY_CHECKED(jboolean,
 945   checked_jni_IsInstanceOf(JNIEnv *env,
 946                            jobject obj,
 947                            jclass clazz))
 948     functionEnter(thr);
 949     IN_VM(
 950       jniCheck::validate_object(thr, obj);
 951       jniCheck::validate_class(thr, clazz, true);
 952     )
 953     jboolean result = UNCHECKED()->IsInstanceOf(env,obj,clazz);
 954     functionExit(thr);
 955     return result;
 956 JNI_END
 957 
 958 JNI_ENTRY_CHECKED(jmethodID,
 959   checked_jni_GetMethodID(JNIEnv *env,
 960                           jclass clazz,
 961                           const char *name,
 962                           const char *sig))
 963     functionEnter(thr);
 964     IN_VM(
 965       jniCheck::validate_class(thr, clazz, false);
 966     )
 967     jmethodID result = UNCHECKED()->GetMethodID(env,clazz,name,sig);
 968     functionExit(thr);
 969     return result;
 970 JNI_END
 971 
 972 #define WRAPPER_CallMethod(ResultType, Result) \
 973 JNI_ENTRY_CHECKED(ResultType,  \
 974   checked_jni_Call##Result##Method(JNIEnv *env, \
 975                                    jobject obj, \
 976                                    jmethodID methodID, \
 977                                    ...)) \
 978     functionEnter(thr); \
 979     va_list args; \
 980     IN_VM( \
 981       jniCheck::validate_call(thr, nullptr, methodID, obj); \
 982     ) \
 983     va_start(args,methodID); \
 984     ResultType result =UNCHECKED()->Call##Result##MethodV(env, obj, methodID, \
 985                                                           args); \
 986     va_end(args); \
 987     thr->set_pending_jni_exception_check("Call"#Result"Method"); \
 988     functionExit(thr); \
 989     return result; \
 990 JNI_END \
 991 \
 992 JNI_ENTRY_CHECKED(ResultType,  \
 993   checked_jni_Call##Result##MethodV(JNIEnv *env, \
 994                                     jobject obj, \
 995                                     jmethodID methodID, \
 996                                     va_list args)) \
 997     functionEnter(thr); \
 998     IN_VM(\
 999       jniCheck::validate_call(thr, nullptr, methodID, obj); \
1000     ) \
1001     ResultType result = UNCHECKED()->Call##Result##MethodV(env, obj, methodID,\
1002                                                            args); \
1003     thr->set_pending_jni_exception_check("Call"#Result"MethodV"); \
1004     functionExit(thr); \
1005     return result; \
1006 JNI_END \
1007 \
1008 JNI_ENTRY_CHECKED(ResultType,  \
1009   checked_jni_Call##Result##MethodA(JNIEnv *env, \
1010                                     jobject obj, \
1011                                     jmethodID methodID, \
1012                                     const jvalue * args)) \
1013     functionEnter(thr); \
1014     IN_VM( \
1015       jniCheck::validate_call(thr, nullptr, methodID, obj); \
1016     ) \
1017     ResultType result = UNCHECKED()->Call##Result##MethodA(env, obj, methodID,\
1018                                                            args); \
1019     thr->set_pending_jni_exception_check("Call"#Result"MethodA"); \
1020     functionExit(thr); \
1021     return result; \
1022 JNI_END
1023 
1024 WRAPPER_CallMethod(jobject,Object)
1025 WRAPPER_CallMethod(jboolean,Boolean)
1026 WRAPPER_CallMethod(jbyte,Byte)
1027 WRAPPER_CallMethod(jshort,Short)
1028 WRAPPER_CallMethod(jchar,Char)
1029 WRAPPER_CallMethod(jint,Int)
1030 WRAPPER_CallMethod(jlong,Long)
1031 WRAPPER_CallMethod(jfloat,Float)
1032 WRAPPER_CallMethod(jdouble,Double)
1033 
1034 JNI_ENTRY_CHECKED(void,
1035   checked_jni_CallVoidMethod(JNIEnv *env, \
1036                              jobject obj, \
1037                              jmethodID methodID, \
1038                              ...))
1039     functionEnter(thr);
1040     va_list args;
1041     IN_VM(
1042       jniCheck::validate_call(thr, nullptr, methodID, obj);
1043     )
1044     va_start(args,methodID);
1045     UNCHECKED()->CallVoidMethodV(env,obj,methodID,args);
1046     va_end(args);
1047     thr->set_pending_jni_exception_check("CallVoidMethod");
1048     functionExit(thr);
1049 JNI_END
1050 
1051 JNI_ENTRY_CHECKED(void,
1052   checked_jni_CallVoidMethodV(JNIEnv *env,
1053                               jobject obj,
1054                               jmethodID methodID,
1055                               va_list args))
1056     functionEnter(thr);
1057     IN_VM(
1058       jniCheck::validate_call(thr, nullptr, methodID, obj);
1059     )
1060     UNCHECKED()->CallVoidMethodV(env,obj,methodID,args);
1061     thr->set_pending_jni_exception_check("CallVoidMethodV");
1062     functionExit(thr);
1063 JNI_END
1064 
1065 JNI_ENTRY_CHECKED(void,
1066   checked_jni_CallVoidMethodA(JNIEnv *env,
1067                               jobject obj,
1068                               jmethodID methodID,
1069                               const jvalue * args))
1070     functionEnter(thr);
1071     IN_VM(
1072       jniCheck::validate_call(thr, nullptr, methodID, obj);
1073     )
1074     UNCHECKED()->CallVoidMethodA(env,obj,methodID,args);
1075     thr->set_pending_jni_exception_check("CallVoidMethodA");
1076     functionExit(thr);
1077 JNI_END
1078 
1079 #define WRAPPER_CallNonvirtualMethod(ResultType, Result) \
1080 JNI_ENTRY_CHECKED(ResultType,  \
1081   checked_jni_CallNonvirtual##Result##Method(JNIEnv *env, \
1082                                              jobject obj, \
1083                                              jclass clazz, \
1084                                              jmethodID methodID, \
1085                                              ...)) \
1086     functionEnter(thr); \
1087     va_list args; \
1088     IN_VM( \
1089       jniCheck::validate_call(thr, clazz, methodID, obj); \
1090     ) \
1091     va_start(args,methodID); \
1092     ResultType result = UNCHECKED()->CallNonvirtual##Result##MethodV(env, \
1093                                                                      obj, \
1094                                                                      clazz, \
1095                                                                      methodID,\
1096                                                                      args); \
1097     va_end(args); \
1098     thr->set_pending_jni_exception_check("CallNonvirtual"#Result"Method"); \
1099     functionExit(thr); \
1100     return result; \
1101 JNI_END \
1102 \
1103 JNI_ENTRY_CHECKED(ResultType,  \
1104   checked_jni_CallNonvirtual##Result##MethodV(JNIEnv *env, \
1105                                               jobject obj, \
1106                                               jclass clazz, \
1107                                               jmethodID methodID, \
1108                                               va_list args)) \
1109     functionEnter(thr); \
1110     IN_VM( \
1111       jniCheck::validate_call(thr, clazz, methodID, obj); \
1112     ) \
1113     ResultType result = UNCHECKED()->CallNonvirtual##Result##MethodV(env, \
1114                                                                      obj, \
1115                                                                      clazz, \
1116                                                                      methodID,\
1117                                                                      args); \
1118     thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodV"); \
1119     functionExit(thr); \
1120     return result; \
1121 JNI_END \
1122 \
1123 JNI_ENTRY_CHECKED(ResultType,  \
1124   checked_jni_CallNonvirtual##Result##MethodA(JNIEnv *env, \
1125                                               jobject obj, \
1126                                               jclass clazz, \
1127                                               jmethodID methodID, \
1128                                               const jvalue * args)) \
1129     functionEnter(thr); \
1130     IN_VM( \
1131       jniCheck::validate_call(thr, clazz, methodID, obj); \
1132     ) \
1133     ResultType result = UNCHECKED()->CallNonvirtual##Result##MethodA(env, \
1134                                                                      obj, \
1135                                                                      clazz, \
1136                                                                      methodID,\
1137                                                                      args); \
1138     thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodA"); \
1139     functionExit(thr); \
1140     return result; \
1141 JNI_END
1142 
1143 WRAPPER_CallNonvirtualMethod(jobject,Object)
1144 WRAPPER_CallNonvirtualMethod(jboolean,Boolean)
1145 WRAPPER_CallNonvirtualMethod(jbyte,Byte)
1146 WRAPPER_CallNonvirtualMethod(jshort,Short)
1147 WRAPPER_CallNonvirtualMethod(jchar,Char)
1148 WRAPPER_CallNonvirtualMethod(jint,Int)
1149 WRAPPER_CallNonvirtualMethod(jlong,Long)
1150 WRAPPER_CallNonvirtualMethod(jfloat,Float)
1151 WRAPPER_CallNonvirtualMethod(jdouble,Double)
1152 
1153 JNI_ENTRY_CHECKED(void,
1154   checked_jni_CallNonvirtualVoidMethod(JNIEnv *env,
1155                                        jobject obj,
1156                                        jclass clazz,
1157                                        jmethodID methodID,
1158                                        ...))
1159     functionEnter(thr);
1160     va_list args;
1161     IN_VM(
1162       jniCheck::validate_call(thr, clazz, methodID, obj);
1163     )
1164     va_start(args,methodID);
1165     UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args);
1166     va_end(args);
1167     thr->set_pending_jni_exception_check("CallNonvirtualVoidMethod");
1168     functionExit(thr);
1169 JNI_END
1170 
1171 JNI_ENTRY_CHECKED(void,
1172   checked_jni_CallNonvirtualVoidMethodV(JNIEnv *env,
1173                                         jobject obj,
1174                                         jclass clazz,
1175                                         jmethodID methodID,
1176                                         va_list args))
1177     functionEnter(thr);
1178     IN_VM(
1179       jniCheck::validate_call(thr, clazz, methodID, obj);
1180     )
1181     UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args);
1182     thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodV");
1183     functionExit(thr);
1184 JNI_END
1185 
1186 JNI_ENTRY_CHECKED(void,
1187   checked_jni_CallNonvirtualVoidMethodA(JNIEnv *env,
1188                                         jobject obj,
1189                                         jclass clazz,
1190                                         jmethodID methodID,
1191                                         const jvalue * args))
1192     functionEnter(thr);
1193     IN_VM(
1194       jniCheck::validate_call(thr, clazz, methodID, obj);
1195     )
1196     UNCHECKED()->CallNonvirtualVoidMethodA(env,obj,clazz,methodID,args);
1197     thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodA");
1198     functionExit(thr);
1199 JNI_END
1200 
1201 JNI_ENTRY_CHECKED(jfieldID,
1202   checked_jni_GetFieldID(JNIEnv *env,
1203                          jclass clazz,
1204                          const char *name,
1205                          const char *sig))
1206     functionEnter(thr);
1207     IN_VM(
1208       jniCheck::validate_class(thr, clazz, false);
1209     )
1210     jfieldID result = UNCHECKED()->GetFieldID(env,clazz,name,sig);
1211     functionExit(thr);
1212     return result;
1213 JNI_END
1214 
1215 #define WRAPPER_GetField(ReturnType,Result,FieldType) \
1216 JNI_ENTRY_CHECKED(ReturnType,  \
1217   checked_jni_Get##Result##Field(JNIEnv *env, \
1218                                  jobject obj, \
1219                                  jfieldID fieldID)) \
1220     functionEnter(thr); \
1221     IN_VM( \
1222       checkInstanceFieldID(thr, fieldID, obj, FieldType, false); \
1223     ) \
1224     ReturnType result = UNCHECKED()->Get##Result##Field(env,obj,fieldID); \
1225     functionExit(thr); \
1226     return result; \
1227 JNI_END
1228 
1229 WRAPPER_GetField(jobject,  Object,  T_OBJECT)
1230 WRAPPER_GetField(jboolean, Boolean, T_BOOLEAN)
1231 WRAPPER_GetField(jbyte,    Byte,    T_BYTE)
1232 WRAPPER_GetField(jshort,   Short,   T_SHORT)
1233 WRAPPER_GetField(jchar,    Char,    T_CHAR)
1234 WRAPPER_GetField(jint,     Int,     T_INT)
1235 WRAPPER_GetField(jlong,    Long,    T_LONG)
1236 WRAPPER_GetField(jfloat,   Float,   T_FLOAT)
1237 WRAPPER_GetField(jdouble,  Double,  T_DOUBLE)
1238 
1239 #define WRAPPER_SetField(ValueType,Result,FieldType) \
1240 JNI_ENTRY_CHECKED(void,  \
1241   checked_jni_Set##Result##Field(JNIEnv *env, \
1242                                  jobject obj, \
1243                                  jfieldID fieldID, \
1244                                  ValueType val)) \
1245     functionEnter(thr); \
1246     IN_VM( \
1247       checkInstanceFieldID(thr, fieldID, obj, FieldType, true); \
1248     ) \
1249     UNCHECKED()->Set##Result##Field(env,obj,fieldID,val); \
1250     functionExit(thr); \
1251 JNI_END
1252 
1253 WRAPPER_SetField(jobject,  Object,  T_OBJECT)
1254 WRAPPER_SetField(jboolean, Boolean, T_BOOLEAN)
1255 WRAPPER_SetField(jbyte,    Byte,    T_BYTE)
1256 WRAPPER_SetField(jshort,   Short,   T_SHORT)
1257 WRAPPER_SetField(jchar,    Char,    T_CHAR)
1258 WRAPPER_SetField(jint,     Int,     T_INT)
1259 WRAPPER_SetField(jlong,    Long,    T_LONG)
1260 WRAPPER_SetField(jfloat,   Float,   T_FLOAT)
1261 WRAPPER_SetField(jdouble,  Double,  T_DOUBLE)
1262 
1263 
1264 JNI_ENTRY_CHECKED(jmethodID,
1265   checked_jni_GetStaticMethodID(JNIEnv *env,
1266                                 jclass clazz,
1267                                 const char *name,
1268                                 const char *sig))
1269     functionEnter(thr);
1270     IN_VM(
1271       jniCheck::validate_class(thr, clazz, false);
1272     )
1273     jmethodID result = UNCHECKED()->GetStaticMethodID(env,clazz,name,sig);
1274     functionExit(thr);
1275     return result;
1276 JNI_END
1277 
1278 #define WRAPPER_CallStaticMethod(ReturnType,Result) \
1279 JNI_ENTRY_CHECKED(ReturnType,  \
1280   checked_jni_CallStatic##Result##Method(JNIEnv *env, \
1281                                          jclass clazz, \
1282                                          jmethodID methodID, \
1283                                          ...)) \
1284     functionEnter(thr); \
1285     va_list args; \
1286     IN_VM( \
1287       jniCheck::validate_call(thr, clazz, methodID); \
1288     ) \
1289     va_start(args,methodID); \
1290     ReturnType result = UNCHECKED()->CallStatic##Result##MethodV(env, \
1291                                                                  clazz, \
1292                                                                  methodID, \
1293                                                                  args); \
1294     va_end(args); \
1295     thr->set_pending_jni_exception_check("CallStatic"#Result"Method"); \
1296     functionExit(thr); \
1297     return result; \
1298 JNI_END \
1299 \
1300 JNI_ENTRY_CHECKED(ReturnType,  \
1301   checked_jni_CallStatic##Result##MethodV(JNIEnv *env, \
1302                                           jclass clazz, \
1303                                           jmethodID methodID,\
1304                                           va_list args)) \
1305     functionEnter(thr); \
1306     IN_VM( \
1307       jniCheck::validate_call(thr, clazz, methodID); \
1308     ) \
1309     ReturnType result = UNCHECKED()->CallStatic##Result##MethodV(env, \
1310                                                                  clazz, \
1311                                                                  methodID, \
1312                                                                  args); \
1313     thr->set_pending_jni_exception_check("CallStatic"#Result"MethodV"); \
1314     functionExit(thr); \
1315     return result; \
1316 JNI_END \
1317 \
1318 JNI_ENTRY_CHECKED(ReturnType,  \
1319   checked_jni_CallStatic##Result##MethodA(JNIEnv *env, \
1320                                           jclass clazz, \
1321                                           jmethodID methodID, \
1322                                           const jvalue *args)) \
1323     functionEnter(thr); \
1324     IN_VM( \
1325       jniCheck::validate_call(thr, clazz, methodID); \
1326     ) \
1327     ReturnType result = UNCHECKED()->CallStatic##Result##MethodA(env, \
1328                                                                  clazz, \
1329                                                                  methodID, \
1330                                                                  args); \
1331     thr->set_pending_jni_exception_check("CallStatic"#Result"MethodA"); \
1332     functionExit(thr); \
1333     return result; \
1334 JNI_END
1335 
1336 WRAPPER_CallStaticMethod(jobject,Object)
1337 WRAPPER_CallStaticMethod(jboolean,Boolean)
1338 WRAPPER_CallStaticMethod(jbyte,Byte)
1339 WRAPPER_CallStaticMethod(jshort,Short)
1340 WRAPPER_CallStaticMethod(jchar,Char)
1341 WRAPPER_CallStaticMethod(jint,Int)
1342 WRAPPER_CallStaticMethod(jlong,Long)
1343 WRAPPER_CallStaticMethod(jfloat,Float)
1344 WRAPPER_CallStaticMethod(jdouble,Double)
1345 
1346 JNI_ENTRY_CHECKED(void,
1347   checked_jni_CallStaticVoidMethod(JNIEnv *env,
1348                                    jclass cls,
1349                                    jmethodID methodID,
1350                                    ...))
1351     functionEnter(thr);
1352     va_list args;
1353     IN_VM(
1354       jniCheck::validate_call(thr, cls, methodID);
1355     )
1356     va_start(args,methodID);
1357     UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args);
1358     va_end(args);
1359     thr->set_pending_jni_exception_check("CallStaticVoidMethod");
1360     functionExit(thr);
1361 JNI_END
1362 
1363 JNI_ENTRY_CHECKED(void,
1364   checked_jni_CallStaticVoidMethodV(JNIEnv *env,
1365                                     jclass cls,
1366                                     jmethodID methodID,
1367                                     va_list args))
1368     functionEnter(thr);
1369     IN_VM(
1370       jniCheck::validate_call(thr, cls, methodID);
1371     )
1372     UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args);
1373     thr->set_pending_jni_exception_check("CallStaticVoidMethodV");
1374     functionExit(thr);
1375 JNI_END
1376 
1377 JNI_ENTRY_CHECKED(void,
1378   checked_jni_CallStaticVoidMethodA(JNIEnv *env,
1379                                     jclass cls,
1380                                     jmethodID methodID,
1381                                     const jvalue * args))
1382     functionEnter(thr);
1383     IN_VM(
1384       jniCheck::validate_call(thr, cls, methodID);
1385     )
1386     UNCHECKED()->CallStaticVoidMethodA(env,cls,methodID,args);
1387     thr->set_pending_jni_exception_check("CallStaticVoidMethodA");
1388     functionExit(thr);
1389 JNI_END
1390 
1391 JNI_ENTRY_CHECKED(jfieldID,
1392   checked_jni_GetStaticFieldID(JNIEnv *env,
1393                                jclass clazz,
1394                                const char *name,
1395                                const char *sig))
1396     functionEnter(thr);
1397     IN_VM(
1398       jniCheck::validate_class(thr, clazz, false);
1399     )
1400     jfieldID result = UNCHECKED()->GetStaticFieldID(env,clazz,name,sig);
1401     functionExit(thr);
1402     return result;
1403 JNI_END
1404 
1405 #define WRAPPER_GetStaticField(ReturnType,Result,FieldType) \
1406 JNI_ENTRY_CHECKED(ReturnType,  \
1407   checked_jni_GetStatic##Result##Field(JNIEnv *env, \
1408                                        jclass clazz, \
1409                                        jfieldID fieldID)) \
1410     functionEnter(thr); \
1411     IN_VM( \
1412       jniCheck::validate_class(thr, clazz, false); \
1413       checkStaticFieldID(thr, fieldID, clazz, FieldType, false); \
1414     ) \
1415     ReturnType result = UNCHECKED()->GetStatic##Result##Field(env, \
1416                                                               clazz, \
1417                                                               fieldID); \
1418     functionExit(thr); \
1419     return result; \
1420 JNI_END
1421 
1422 WRAPPER_GetStaticField(jobject,  Object,  T_OBJECT)
1423 WRAPPER_GetStaticField(jboolean, Boolean, T_BOOLEAN)
1424 WRAPPER_GetStaticField(jbyte,    Byte,    T_BYTE)
1425 WRAPPER_GetStaticField(jshort,   Short,   T_SHORT)
1426 WRAPPER_GetStaticField(jchar,    Char,    T_CHAR)
1427 WRAPPER_GetStaticField(jint,     Int,     T_INT)
1428 WRAPPER_GetStaticField(jlong,    Long,    T_LONG)
1429 WRAPPER_GetStaticField(jfloat,   Float,   T_FLOAT)
1430 WRAPPER_GetStaticField(jdouble,  Double,  T_DOUBLE)
1431 
1432 #define WRAPPER_SetStaticField(ValueType,Result,FieldType) \
1433 JNI_ENTRY_CHECKED(void,  \
1434   checked_jni_SetStatic##Result##Field(JNIEnv *env, \
1435                                        jclass clazz, \
1436                                        jfieldID fieldID, \
1437                                        ValueType value)) \
1438     functionEnter(thr); \
1439     IN_VM( \
1440       jniCheck::validate_class(thr, clazz, false); \
1441       checkStaticFieldID(thr, fieldID, clazz, FieldType, true); \
1442     ) \
1443     UNCHECKED()->SetStatic##Result##Field(env,clazz,fieldID,value); \
1444     functionExit(thr); \
1445 JNI_END
1446 
1447 WRAPPER_SetStaticField(jobject,  Object,  T_OBJECT)
1448 WRAPPER_SetStaticField(jboolean, Boolean, T_BOOLEAN)
1449 WRAPPER_SetStaticField(jbyte,    Byte,    T_BYTE)
1450 WRAPPER_SetStaticField(jshort,   Short,   T_SHORT)
1451 WRAPPER_SetStaticField(jchar,    Char,    T_CHAR)
1452 WRAPPER_SetStaticField(jint,     Int,     T_INT)
1453 WRAPPER_SetStaticField(jlong,    Long,    T_LONG)
1454 WRAPPER_SetStaticField(jfloat,   Float,   T_FLOAT)
1455 WRAPPER_SetStaticField(jdouble,  Double,  T_DOUBLE)
1456 
1457 
1458 JNI_ENTRY_CHECKED(jstring,
1459   checked_jni_NewString(JNIEnv *env,
1460                         const jchar *unicode,
1461                         jsize len))
1462     functionEnter(thr);
1463     jstring result = UNCHECKED()->NewString(env,unicode,len);
1464     functionExit(thr);
1465     return result;
1466 JNI_END
1467 
1468 JNI_ENTRY_CHECKED(jsize,
1469   checked_jni_GetStringLength(JNIEnv *env,
1470                               jstring str))
1471     functionEnter(thr);
1472     IN_VM(
1473       checkString(thr, str);
1474     )
1475     jsize result = UNCHECKED()->GetStringLength(env,str);
1476     functionExit(thr);
1477     return result;
1478 JNI_END
1479 
1480 JNI_ENTRY_CHECKED(const jchar *,
1481   checked_jni_GetStringChars(JNIEnv *env,
1482                              jstring str,
1483                              jboolean *isCopy))
1484     functionEnter(thr);
1485     IN_VM(
1486       checkString(thr, str);
1487     )
1488     jchar* new_result = nullptr;
1489     const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
1490     assert (isCopy == nullptr || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
1491     if (result != nullptr) {
1492       size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for null termination
1493       len *= sizeof(jchar);
1494       new_result = (jchar*) GuardedMemory::wrap_copy(result, len, STRING_TAG);
1495       if (new_result == nullptr) {
1496         vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringChars");
1497       }
1498       // Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes
1499       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
1500       FreeHeap((char*)result);
1501     }
1502     functionExit(thr);
1503     return new_result;
1504 JNI_END
1505 
1506 JNI_ENTRY_CHECKED(void,
1507   checked_jni_ReleaseStringChars(JNIEnv *env,
1508                                  jstring str,
1509                                  const jchar *chars))
1510     functionEnterExceptionAllowed(thr);
1511     IN_VM(
1512       checkString(thr, str);
1513     )
1514     if (chars == nullptr) {
1515        // still do the unchecked call to allow dtrace probes
1516        UNCHECKED()->ReleaseStringChars(env,str,chars);
1517     }
1518     else {
1519       GuardedMemory guarded((void*)chars);
1520       if (!guarded.verify_guards()) {
1521         tty->print_cr("ReleaseStringChars: release chars failed bounds check. "
1522             "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars));
1523         guarded.print_on(tty);
1524         NativeReportJNIFatalError(thr, "ReleaseStringChars: "
1525             "release chars failed bounds check.");
1526       }
1527       if (guarded.get_tag() != STRING_TAG) {
1528         tty->print_cr("ReleaseStringChars: called on something not allocated "
1529             "by GetStringChars. string: " PTR_FORMAT " chars: " PTR_FORMAT,
1530             p2i(str), p2i(chars));
1531         NativeReportJNIFatalError(thr, "ReleaseStringChars called on something "
1532             "not allocated by GetStringChars");
1533       }
1534        UNCHECKED()->ReleaseStringChars(env, str,
1535            (const jchar*) guarded.release_for_freeing());
1536     }
1537     functionExit(thr);
1538 JNI_END
1539 
1540 JNI_ENTRY_CHECKED(jstring,
1541   checked_jni_NewStringUTF(JNIEnv *env,
1542                            const char *utf))
1543     functionEnter(thr);
1544     jstring result = UNCHECKED()->NewStringUTF(env,utf);
1545     functionExit(thr);
1546     return result;
1547 JNI_END
1548 
1549 JNI_ENTRY_CHECKED(jsize,
1550   checked_jni_GetStringUTFLength(JNIEnv *env,
1551                                  jstring str))
1552     functionEnter(thr);
1553     IN_VM(
1554       checkString(thr, str);
1555     )
1556     jsize result = UNCHECKED()->GetStringUTFLength(env,str);
1557     jlong full_length =  UNCHECKED()->GetStringUTFLengthAsLong(env,str);
1558     if (full_length > result) {
1559       ResourceMark rm(thr);
1560       stringStream ss;
1561       ss.print("WARNING: large String with modified UTF-8 length " JLONG_FORMAT
1562                 " is reporting a reduced length of %d - use GetStringUTFLengthAsLong instead",
1563                 full_length, result);
1564       NativeReportJNIWarning(thr, ss.as_string());
1565     }
1566     functionExit(thr);
1567     return result;
1568 JNI_END
1569 
1570 JNI_ENTRY_CHECKED(jlong,
1571   checked_jni_GetStringUTFLengthAsLong(JNIEnv *env,
1572                                        jstring str))
1573     functionEnter(thr);
1574     IN_VM(
1575       checkString(thr, str);
1576     )
1577     jlong result = UNCHECKED()->GetStringUTFLengthAsLong(env,str);
1578     functionExit(thr);
1579     return result;
1580 JNI_END
1581 
1582 JNI_ENTRY_CHECKED(const char *,
1583   checked_jni_GetStringUTFChars(JNIEnv *env,
1584                                 jstring str,
1585                                 jboolean *isCopy))
1586     functionEnter(thr);
1587     IN_VM(
1588       checkString(thr, str);
1589     )
1590     char* new_result = nullptr;
1591     const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
1592     assert (isCopy == nullptr || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
1593     if (result != nullptr) {
1594       size_t len = strlen(result) + 1; // + 1 for null termination
1595       new_result = (char*) GuardedMemory::wrap_copy(result, len, STRING_UTF_TAG);
1596       if (new_result == nullptr) {
1597         vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringUTFChars");
1598       }
1599       // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
1600       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
1601       FreeHeap((char*)result);
1602     }
1603     functionExit(thr);
1604     return new_result;
1605 JNI_END
1606 
1607 JNI_ENTRY_CHECKED(void,
1608   checked_jni_ReleaseStringUTFChars(JNIEnv *env,
1609                                     jstring str,
1610                                     const char* chars))
1611     functionEnterExceptionAllowed(thr);
1612     IN_VM(
1613       checkString(thr, str);
1614     )
1615     if (chars == nullptr) {
1616        // still do the unchecked call to allow dtrace probes
1617        UNCHECKED()->ReleaseStringUTFChars(env,str,chars);
1618     }
1619     else {
1620       GuardedMemory guarded((void*)chars);
1621       if (!guarded.verify_guards()) {
1622         tty->print_cr("ReleaseStringUTFChars: release chars failed bounds check. "
1623             "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars));
1624         guarded.print_on(tty);
1625         NativeReportJNIFatalError(thr, "ReleaseStringUTFChars: "
1626             "release chars failed bounds check.");
1627       }
1628       if (guarded.get_tag() != STRING_UTF_TAG) {
1629         tty->print_cr("ReleaseStringUTFChars: called on something not "
1630             "allocated by GetStringUTFChars. string: " PTR_FORMAT " chars: "
1631             PTR_FORMAT, p2i(str), p2i(chars));
1632         NativeReportJNIFatalError(thr, "ReleaseStringUTFChars "
1633             "called on something not allocated by GetStringUTFChars");
1634       }
1635       UNCHECKED()->ReleaseStringUTFChars(env, str,
1636           (const char*) guarded.release_for_freeing());
1637     }
1638     functionExit(thr);
1639 JNI_END
1640 
1641 JNI_ENTRY_CHECKED(jsize,
1642   checked_jni_GetArrayLength(JNIEnv *env,
1643                              jarray array))
1644     functionEnter(thr);
1645     IN_VM(
1646       check_is_array(thr, array);
1647     )
1648     jsize result = UNCHECKED()->GetArrayLength(env,array);
1649     functionExit(thr);
1650     return result;
1651 JNI_END
1652 
1653 JNI_ENTRY_CHECKED(jobjectArray,
1654   checked_jni_NewObjectArray(JNIEnv *env,
1655                              jsize len,
1656                              jclass clazz,
1657                              jobject init))
1658     functionEnter(thr);
1659     jobjectArray result = UNCHECKED()->NewObjectArray(env,len,clazz,init);
1660     functionExit(thr);
1661     return result;
1662 JNI_END
1663 
1664 JNI_ENTRY_CHECKED(jobject,
1665   checked_jni_GetObjectArrayElement(JNIEnv *env,
1666                                     jobjectArray array,
1667                                     jsize index))
1668     functionEnter(thr);
1669     IN_VM(
1670       check_is_obj_array(thr, array);
1671     )
1672     jobject result = UNCHECKED()->GetObjectArrayElement(env,array,index);
1673     functionExit(thr);
1674     return result;
1675 JNI_END
1676 
1677 JNI_ENTRY_CHECKED(void,
1678   checked_jni_SetObjectArrayElement(JNIEnv *env,
1679                                     jobjectArray array,
1680                                     jsize index,
1681                                     jobject val))
1682     functionEnter(thr);
1683     IN_VM(
1684       check_is_obj_array(thr, array);
1685     )
1686     UNCHECKED()->SetObjectArrayElement(env,array,index,val);
1687     functionExit(thr);
1688 JNI_END
1689 
1690 #define WRAPPER_NewScalarArray(Return, Result) \
1691 JNI_ENTRY_CHECKED(Return, \
1692   checked_jni_New##Result##Array(JNIEnv *env, \
1693                                  jsize len)) \
1694     functionEnter(thr); \
1695     Return result = UNCHECKED()->New##Result##Array(env,len); \
1696     functionExit(thr); \
1697     return (Return) result; \
1698 JNI_END
1699 
1700 WRAPPER_NewScalarArray(jbooleanArray, Boolean)
1701 WRAPPER_NewScalarArray(jbyteArray, Byte)
1702 WRAPPER_NewScalarArray(jshortArray, Short)
1703 WRAPPER_NewScalarArray(jcharArray, Char)
1704 WRAPPER_NewScalarArray(jintArray, Int)
1705 WRAPPER_NewScalarArray(jlongArray, Long)
1706 WRAPPER_NewScalarArray(jfloatArray, Float)
1707 WRAPPER_NewScalarArray(jdoubleArray, Double)
1708 
1709 #define WRAPPER_GetScalarArrayElements(ElementTag,ElementType,Result) \
1710 JNI_ENTRY_CHECKED(ElementType *,  \
1711   checked_jni_Get##Result##ArrayElements(JNIEnv *env, \
1712                                          ElementType##Array array, \
1713                                          jboolean *isCopy)) \
1714     functionEnter(thr); \
1715     IN_VM( \
1716       check_primitive_array_type(thr, array, ElementTag); \
1717     ) \
1718     ElementType *result = UNCHECKED()->Get##Result##ArrayElements(env, \
1719                                                                   array, \
1720                                                                   isCopy); \
1721     if (result != nullptr) { \
1722       result = (ElementType *) check_jni_wrap_copy_array(thr, array, result); \
1723     } \
1724     functionExit(thr); \
1725     return result; \
1726 JNI_END
1727 
1728 WRAPPER_GetScalarArrayElements(T_BOOLEAN, jboolean, Boolean)
1729 WRAPPER_GetScalarArrayElements(T_BYTE,    jbyte,    Byte)
1730 WRAPPER_GetScalarArrayElements(T_SHORT,   jshort,   Short)
1731 WRAPPER_GetScalarArrayElements(T_CHAR,    jchar,    Char)
1732 WRAPPER_GetScalarArrayElements(T_INT,     jint,     Int)
1733 WRAPPER_GetScalarArrayElements(T_LONG,    jlong,    Long)
1734 WRAPPER_GetScalarArrayElements(T_FLOAT,   jfloat,   Float)
1735 WRAPPER_GetScalarArrayElements(T_DOUBLE,  jdouble,  Double)
1736 
1737 #define WRAPPER_ReleaseScalarArrayElements(ElementTag,ElementType,Result,Tag) \
1738 JNI_ENTRY_CHECKED(void,  \
1739   checked_jni_Release##Result##ArrayElements(JNIEnv *env, \
1740                                              ElementType##Array array, \
1741                                              ElementType *elems, \
1742                                              jint mode)) \
1743     functionEnterExceptionAllowed(thr); \
1744     IN_VM( \
1745       check_primitive_array_type(thr, array, ElementTag); \
1746       ASSERT_OOPS_ALLOWED; \
1747       typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
1748     ) \
1749     ElementType* orig_result = (ElementType *) check_wrapped_array_release( \
1750         thr, "checked_jni_Release"#Result"ArrayElements", array, elems, mode, JNI_FALSE); \
1751     UNCHECKED()->Release##Result##ArrayElements(env, array, orig_result, mode); \
1752     functionExit(thr); \
1753 JNI_END
1754 
1755 WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool)
1756 WRAPPER_ReleaseScalarArrayElements(T_BYTE,   jbyte,    Byte,    byte)
1757 WRAPPER_ReleaseScalarArrayElements(T_SHORT,  jshort,   Short,   short)
1758 WRAPPER_ReleaseScalarArrayElements(T_CHAR,   jchar,    Char,    char)
1759 WRAPPER_ReleaseScalarArrayElements(T_INT,    jint,     Int,     int)
1760 WRAPPER_ReleaseScalarArrayElements(T_LONG,   jlong,    Long,    long)
1761 WRAPPER_ReleaseScalarArrayElements(T_FLOAT,  jfloat,   Float,   float)
1762 WRAPPER_ReleaseScalarArrayElements(T_DOUBLE, jdouble,  Double,  double)
1763 
1764 #define WRAPPER_GetScalarArrayRegion(ElementTag,ElementType,Result) \
1765 JNI_ENTRY_CHECKED(void,  \
1766   checked_jni_Get##Result##ArrayRegion(JNIEnv *env, \
1767                                        ElementType##Array array, \
1768                                        jsize start, \
1769                                        jsize len, \
1770                                        ElementType *buf)) \
1771     functionEnter(thr); \
1772     IN_VM( \
1773       check_primitive_array_type(thr, array, ElementTag); \
1774     ) \
1775     UNCHECKED()->Get##Result##ArrayRegion(env,array,start,len,buf); \
1776     functionExit(thr); \
1777 JNI_END
1778 
1779 WRAPPER_GetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean)
1780 WRAPPER_GetScalarArrayRegion(T_BYTE,    jbyte,    Byte)
1781 WRAPPER_GetScalarArrayRegion(T_SHORT,   jshort,   Short)
1782 WRAPPER_GetScalarArrayRegion(T_CHAR,    jchar,    Char)
1783 WRAPPER_GetScalarArrayRegion(T_INT,     jint,     Int)
1784 WRAPPER_GetScalarArrayRegion(T_LONG,    jlong,    Long)
1785 WRAPPER_GetScalarArrayRegion(T_FLOAT,   jfloat,   Float)
1786 WRAPPER_GetScalarArrayRegion(T_DOUBLE,  jdouble,  Double)
1787 
1788 #define WRAPPER_SetScalarArrayRegion(ElementTag,ElementType,Result) \
1789 JNI_ENTRY_CHECKED(void,  \
1790   checked_jni_Set##Result##ArrayRegion(JNIEnv *env, \
1791                                        ElementType##Array array, \
1792                                        jsize start, \
1793                                        jsize len, \
1794                                        const ElementType *buf)) \
1795     functionEnter(thr); \
1796     IN_VM( \
1797       check_primitive_array_type(thr, array, ElementTag); \
1798     ) \
1799     UNCHECKED()->Set##Result##ArrayRegion(env,array,start,len,buf); \
1800     functionExit(thr); \
1801 JNI_END
1802 
1803 WRAPPER_SetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean)
1804 WRAPPER_SetScalarArrayRegion(T_BYTE,    jbyte,    Byte)
1805 WRAPPER_SetScalarArrayRegion(T_SHORT,   jshort,   Short)
1806 WRAPPER_SetScalarArrayRegion(T_CHAR,    jchar,    Char)
1807 WRAPPER_SetScalarArrayRegion(T_INT,     jint,     Int)
1808 WRAPPER_SetScalarArrayRegion(T_LONG,    jlong,    Long)
1809 WRAPPER_SetScalarArrayRegion(T_FLOAT,   jfloat,   Float)
1810 WRAPPER_SetScalarArrayRegion(T_DOUBLE,  jdouble,  Double)
1811 
1812 JNI_ENTRY_CHECKED(jint,
1813   checked_jni_RegisterNatives(JNIEnv *env,
1814                               jclass clazz,
1815                               const JNINativeMethod *methods,
1816                               jint nMethods))
1817     functionEnter(thr);
1818     jint result = UNCHECKED()->RegisterNatives(env,clazz,methods,nMethods);
1819     functionExit(thr);
1820     return result;
1821 JNI_END
1822 
1823 JNI_ENTRY_CHECKED(jint,
1824   checked_jni_UnregisterNatives(JNIEnv *env,
1825                                 jclass clazz))
1826     functionEnter(thr);
1827     jint result = UNCHECKED()->UnregisterNatives(env,clazz);
1828     functionExit(thr);
1829     return result;
1830 JNI_END
1831 
1832 JNI_ENTRY_CHECKED(jint,
1833   checked_jni_MonitorEnter(JNIEnv *env,
1834                            jobject obj))
1835     functionEnter(thr);
1836     IN_VM(
1837       jniCheck::validate_object(thr, obj);
1838     )
1839     jint result = UNCHECKED()->MonitorEnter(env,obj);
1840     functionExit(thr);
1841     return result;
1842 JNI_END
1843 
1844 JNI_ENTRY_CHECKED(jint,
1845   checked_jni_MonitorExit(JNIEnv *env,
1846                           jobject obj))
1847     functionEnterExceptionAllowed(thr);
1848     IN_VM(
1849       jniCheck::validate_object(thr, obj);
1850     )
1851     jint result = UNCHECKED()->MonitorExit(env,obj);
1852     functionExit(thr);
1853     return result;
1854 JNI_END
1855 
1856 JNI_ENTRY_CHECKED(jint,
1857   checked_jni_GetJavaVM(JNIEnv *env,
1858                         JavaVM **vm))
1859     functionEnter(thr);
1860     jint result = UNCHECKED()->GetJavaVM(env,vm);
1861     functionExit(thr);
1862     return result;
1863 JNI_END
1864 
1865 JNI_ENTRY_CHECKED(void,
1866   checked_jni_GetStringRegion(JNIEnv *env,
1867                               jstring str,
1868                               jsize start,
1869                               jsize len,
1870                               jchar *buf))
1871     functionEnter(thr);
1872     IN_VM(
1873       checkString(thr, str);
1874     )
1875     UNCHECKED()->GetStringRegion(env, str, start, len, buf);
1876     functionExit(thr);
1877 JNI_END
1878 
1879 JNI_ENTRY_CHECKED(void,
1880   checked_jni_GetStringUTFRegion(JNIEnv *env,
1881                                  jstring str,
1882                                  jsize start,
1883                                  jsize len,
1884                                  char *buf))
1885     functionEnter(thr);
1886     IN_VM(
1887       checkString(thr, str);
1888     )
1889     UNCHECKED()->GetStringUTFRegion(env, str, start, len, buf);
1890     functionExit(thr);
1891 JNI_END
1892 
1893 JNI_ENTRY_CHECKED(void *,
1894   checked_jni_GetPrimitiveArrayCritical(JNIEnv *env,
1895                                         jarray array,
1896                                         jboolean *isCopy))
1897     functionEnterCritical(thr);
1898     IN_VM(
1899       check_is_primitive_array(thr, array);
1900     )
1901     void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy);
1902     if (result != nullptr) {
1903       result = check_jni_wrap_copy_array(thr, array, result, JNI_TRUE);
1904     }
1905     functionExit(thr);
1906     return result;
1907 JNI_END
1908 
1909 JNI_ENTRY_CHECKED(void,
1910   checked_jni_ReleasePrimitiveArrayCritical(JNIEnv *env,
1911                                             jarray array,
1912                                             void *carray,
1913                                             jint mode))
1914     functionEnterCriticalExceptionAllowed(thr);
1915     IN_VM(
1916       check_is_primitive_array(thr, array);
1917     )
1918     // Check the element array...
1919     void* orig_result = check_wrapped_array_release(thr, "ReleasePrimitiveArrayCritical",
1920                                                     array, carray, mode, JNI_TRUE);
1921     UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, orig_result, mode);
1922     functionExit(thr);
1923 JNI_END
1924 
1925 JNI_ENTRY_CHECKED(const jchar*,
1926   checked_jni_GetStringCritical(JNIEnv *env,
1927                                 jstring string,
1928                                 jboolean *isCopy))
1929     functionEnterCritical(thr);
1930     IN_VM(
1931       checkString(thr, string);
1932     )
1933     const jchar *result = UNCHECKED()->GetStringCritical(env, string, isCopy);
1934     functionExit(thr);
1935     return result;
1936 JNI_END
1937 
1938 JNI_ENTRY_CHECKED(void,
1939   checked_jni_ReleaseStringCritical(JNIEnv *env,
1940                                     jstring str,
1941                                     const jchar *chars))
1942     functionEnterCriticalExceptionAllowed(thr);
1943     IN_VM(
1944       checkString(thr, str);
1945     )
1946     /* The Hotspot JNI code does not use the parameters, so just check the
1947      * string parameter as a minor sanity check
1948      */
1949     UNCHECKED()->ReleaseStringCritical(env, str, chars);
1950     functionExit(thr);
1951 JNI_END
1952 
1953 JNI_ENTRY_CHECKED(jweak,
1954   checked_jni_NewWeakGlobalRef(JNIEnv *env,
1955                                jobject obj))
1956     functionEnter(thr);
1957     IN_VM(
1958       if (obj != nullptr) {
1959         jniCheck::validate_handle(thr, obj);
1960       }
1961     )
1962     jweak result = UNCHECKED()->NewWeakGlobalRef(env, obj);
1963     functionExit(thr);
1964     return result;
1965 JNI_END
1966 
1967 JNI_ENTRY_CHECKED(void,
1968   checked_jni_DeleteWeakGlobalRef(JNIEnv *env,
1969                                   jweak ref))
1970     functionEnterExceptionAllowed(thr);
1971     IN_VM(
1972       if (ref && !JNIHandles::is_weak_global_handle(ref)) {
1973         ReportJNIFatalError(thr,
1974              "Invalid weak global JNI handle passed to DeleteWeakGlobalRef");
1975       }
1976     )
1977     UNCHECKED()->DeleteWeakGlobalRef(env, ref);
1978     functionExit(thr);
1979 JNI_END
1980 
1981 JNI_ENTRY_CHECKED(jboolean,
1982   checked_jni_ExceptionCheck(JNIEnv *env))
1983     thr->clear_pending_jni_exception_check();
1984     functionEnterExceptionAllowed(thr);
1985     jboolean result = UNCHECKED()->ExceptionCheck(env);
1986     functionExit(thr);
1987     return result;
1988 JNI_END
1989 
1990 JNI_ENTRY_CHECKED(jobject,
1991   checked_jni_NewDirectByteBuffer(JNIEnv *env,
1992                                   void *address,
1993                                   jlong capacity))
1994     functionEnter(thr);
1995     jobject result = UNCHECKED()->NewDirectByteBuffer(env, address, capacity);
1996     functionExit(thr);
1997     return result;
1998 JNI_END
1999 
2000 JNI_ENTRY_CHECKED(void *,
2001   checked_jni_GetDirectBufferAddress(JNIEnv *env,
2002                                      jobject buf))
2003     functionEnter(thr);
2004     void* result = UNCHECKED()->GetDirectBufferAddress(env, buf);
2005     functionExit(thr);
2006     return result;
2007 JNI_END
2008 
2009 JNI_ENTRY_CHECKED(jlong,
2010   checked_jni_GetDirectBufferCapacity(JNIEnv *env,
2011                                       jobject buf))
2012     functionEnter(thr);
2013     jlong result = UNCHECKED()->GetDirectBufferCapacity(env, buf);
2014     functionExit(thr);
2015     return result;
2016 JNI_END
2017 
2018 JNI_ENTRY_CHECKED(jobjectRefType,
2019   checked_jni_GetObjectRefType(JNIEnv *env,
2020                                jobject obj))
2021     functionEnter(thr);
2022     /* validate the object being passed */
2023     IN_VM(
2024       jniCheck::validate_object(thr, obj);
2025     )
2026     jobjectRefType result = UNCHECKED()->GetObjectRefType(env, obj);
2027     functionExit(thr);
2028     return result;
2029 JNI_END
2030 
2031 
2032 JNI_ENTRY_CHECKED(jint,
2033   checked_jni_GetVersion(JNIEnv *env))
2034     functionEnter(thr);
2035     jint result = UNCHECKED()->GetVersion(env);
2036     functionExit(thr);
2037     return result;
2038 JNI_END
2039 
2040 JNI_ENTRY_CHECKED(jobject,
2041   checked_jni_GetModule(JNIEnv *env,
2042                         jclass clazz))
2043     functionEnter(thr);
2044     jobject result = UNCHECKED()->GetModule(env, clazz);
2045     functionExit(thr);
2046     return result;
2047 JNI_END
2048 
2049 JNI_ENTRY_CHECKED(jboolean,
2050   checked_jni_IsVirtualThread(JNIEnv *env,
2051                               jobject obj))
2052     functionEnter(thr);
2053     jboolean result = UNCHECKED()->IsVirtualThread(env, obj);
2054     functionExit(thr);
2055     return result;
2056 JNI_END
2057 
2058 /*
2059  * Structure containing all checked jni functions
2060  */
2061 struct JNINativeInterface_  checked_jni_NativeInterface = {
2062     nullptr,
2063     nullptr,
2064     nullptr,
2065 
2066     nullptr,
2067 
2068     checked_jni_GetVersion,
2069 
2070     checked_jni_DefineClass,
2071     checked_jni_FindClass,
2072 
2073     checked_jni_FromReflectedMethod,
2074     checked_jni_FromReflectedField,
2075 
2076     checked_jni_ToReflectedMethod,
2077 
2078     checked_jni_GetSuperclass,
2079     checked_jni_IsAssignableFrom,
2080 
2081     checked_jni_ToReflectedField,
2082 
2083     checked_jni_Throw,
2084     checked_jni_ThrowNew,
2085     checked_jni_ExceptionOccurred,
2086     checked_jni_ExceptionDescribe,
2087     checked_jni_ExceptionClear,
2088     checked_jni_FatalError,
2089 
2090     checked_jni_PushLocalFrame,
2091     checked_jni_PopLocalFrame,
2092 
2093     checked_jni_NewGlobalRef,
2094     checked_jni_DeleteGlobalRef,
2095     checked_jni_DeleteLocalRef,
2096     checked_jni_IsSameObject,
2097 
2098     checked_jni_NewLocalRef,
2099     checked_jni_EnsureLocalCapacity,
2100 
2101     checked_jni_AllocObject,
2102     checked_jni_NewObject,
2103     checked_jni_NewObjectV,
2104     checked_jni_NewObjectA,
2105 
2106     checked_jni_GetObjectClass,
2107     checked_jni_IsInstanceOf,
2108 
2109     checked_jni_GetMethodID,
2110 
2111     checked_jni_CallObjectMethod,
2112     checked_jni_CallObjectMethodV,
2113     checked_jni_CallObjectMethodA,
2114     checked_jni_CallBooleanMethod,
2115     checked_jni_CallBooleanMethodV,
2116     checked_jni_CallBooleanMethodA,
2117     checked_jni_CallByteMethod,
2118     checked_jni_CallByteMethodV,
2119     checked_jni_CallByteMethodA,
2120     checked_jni_CallCharMethod,
2121     checked_jni_CallCharMethodV,
2122     checked_jni_CallCharMethodA,
2123     checked_jni_CallShortMethod,
2124     checked_jni_CallShortMethodV,
2125     checked_jni_CallShortMethodA,
2126     checked_jni_CallIntMethod,
2127     checked_jni_CallIntMethodV,
2128     checked_jni_CallIntMethodA,
2129     checked_jni_CallLongMethod,
2130     checked_jni_CallLongMethodV,
2131     checked_jni_CallLongMethodA,
2132     checked_jni_CallFloatMethod,
2133     checked_jni_CallFloatMethodV,
2134     checked_jni_CallFloatMethodA,
2135     checked_jni_CallDoubleMethod,
2136     checked_jni_CallDoubleMethodV,
2137     checked_jni_CallDoubleMethodA,
2138     checked_jni_CallVoidMethod,
2139     checked_jni_CallVoidMethodV,
2140     checked_jni_CallVoidMethodA,
2141 
2142     checked_jni_CallNonvirtualObjectMethod,
2143     checked_jni_CallNonvirtualObjectMethodV,
2144     checked_jni_CallNonvirtualObjectMethodA,
2145     checked_jni_CallNonvirtualBooleanMethod,
2146     checked_jni_CallNonvirtualBooleanMethodV,
2147     checked_jni_CallNonvirtualBooleanMethodA,
2148     checked_jni_CallNonvirtualByteMethod,
2149     checked_jni_CallNonvirtualByteMethodV,
2150     checked_jni_CallNonvirtualByteMethodA,
2151     checked_jni_CallNonvirtualCharMethod,
2152     checked_jni_CallNonvirtualCharMethodV,
2153     checked_jni_CallNonvirtualCharMethodA,
2154     checked_jni_CallNonvirtualShortMethod,
2155     checked_jni_CallNonvirtualShortMethodV,
2156     checked_jni_CallNonvirtualShortMethodA,
2157     checked_jni_CallNonvirtualIntMethod,
2158     checked_jni_CallNonvirtualIntMethodV,
2159     checked_jni_CallNonvirtualIntMethodA,
2160     checked_jni_CallNonvirtualLongMethod,
2161     checked_jni_CallNonvirtualLongMethodV,
2162     checked_jni_CallNonvirtualLongMethodA,
2163     checked_jni_CallNonvirtualFloatMethod,
2164     checked_jni_CallNonvirtualFloatMethodV,
2165     checked_jni_CallNonvirtualFloatMethodA,
2166     checked_jni_CallNonvirtualDoubleMethod,
2167     checked_jni_CallNonvirtualDoubleMethodV,
2168     checked_jni_CallNonvirtualDoubleMethodA,
2169     checked_jni_CallNonvirtualVoidMethod,
2170     checked_jni_CallNonvirtualVoidMethodV,
2171     checked_jni_CallNonvirtualVoidMethodA,
2172 
2173     checked_jni_GetFieldID,
2174 
2175     checked_jni_GetObjectField,
2176     checked_jni_GetBooleanField,
2177     checked_jni_GetByteField,
2178     checked_jni_GetCharField,
2179     checked_jni_GetShortField,
2180     checked_jni_GetIntField,
2181     checked_jni_GetLongField,
2182     checked_jni_GetFloatField,
2183     checked_jni_GetDoubleField,
2184 
2185     checked_jni_SetObjectField,
2186     checked_jni_SetBooleanField,
2187     checked_jni_SetByteField,
2188     checked_jni_SetCharField,
2189     checked_jni_SetShortField,
2190     checked_jni_SetIntField,
2191     checked_jni_SetLongField,
2192     checked_jni_SetFloatField,
2193     checked_jni_SetDoubleField,
2194 
2195     checked_jni_GetStaticMethodID,
2196 
2197     checked_jni_CallStaticObjectMethod,
2198     checked_jni_CallStaticObjectMethodV,
2199     checked_jni_CallStaticObjectMethodA,
2200     checked_jni_CallStaticBooleanMethod,
2201     checked_jni_CallStaticBooleanMethodV,
2202     checked_jni_CallStaticBooleanMethodA,
2203     checked_jni_CallStaticByteMethod,
2204     checked_jni_CallStaticByteMethodV,
2205     checked_jni_CallStaticByteMethodA,
2206     checked_jni_CallStaticCharMethod,
2207     checked_jni_CallStaticCharMethodV,
2208     checked_jni_CallStaticCharMethodA,
2209     checked_jni_CallStaticShortMethod,
2210     checked_jni_CallStaticShortMethodV,
2211     checked_jni_CallStaticShortMethodA,
2212     checked_jni_CallStaticIntMethod,
2213     checked_jni_CallStaticIntMethodV,
2214     checked_jni_CallStaticIntMethodA,
2215     checked_jni_CallStaticLongMethod,
2216     checked_jni_CallStaticLongMethodV,
2217     checked_jni_CallStaticLongMethodA,
2218     checked_jni_CallStaticFloatMethod,
2219     checked_jni_CallStaticFloatMethodV,
2220     checked_jni_CallStaticFloatMethodA,
2221     checked_jni_CallStaticDoubleMethod,
2222     checked_jni_CallStaticDoubleMethodV,
2223     checked_jni_CallStaticDoubleMethodA,
2224     checked_jni_CallStaticVoidMethod,
2225     checked_jni_CallStaticVoidMethodV,
2226     checked_jni_CallStaticVoidMethodA,
2227 
2228     checked_jni_GetStaticFieldID,
2229 
2230     checked_jni_GetStaticObjectField,
2231     checked_jni_GetStaticBooleanField,
2232     checked_jni_GetStaticByteField,
2233     checked_jni_GetStaticCharField,
2234     checked_jni_GetStaticShortField,
2235     checked_jni_GetStaticIntField,
2236     checked_jni_GetStaticLongField,
2237     checked_jni_GetStaticFloatField,
2238     checked_jni_GetStaticDoubleField,
2239 
2240     checked_jni_SetStaticObjectField,
2241     checked_jni_SetStaticBooleanField,
2242     checked_jni_SetStaticByteField,
2243     checked_jni_SetStaticCharField,
2244     checked_jni_SetStaticShortField,
2245     checked_jni_SetStaticIntField,
2246     checked_jni_SetStaticLongField,
2247     checked_jni_SetStaticFloatField,
2248     checked_jni_SetStaticDoubleField,
2249 
2250     checked_jni_NewString,
2251     checked_jni_GetStringLength,
2252     checked_jni_GetStringChars,
2253     checked_jni_ReleaseStringChars,
2254 
2255     checked_jni_NewStringUTF,
2256     checked_jni_GetStringUTFLength,
2257     checked_jni_GetStringUTFChars,
2258     checked_jni_ReleaseStringUTFChars,
2259 
2260     checked_jni_GetArrayLength,
2261 
2262     checked_jni_NewObjectArray,
2263     checked_jni_GetObjectArrayElement,
2264     checked_jni_SetObjectArrayElement,
2265 
2266     checked_jni_NewBooleanArray,
2267     checked_jni_NewByteArray,
2268     checked_jni_NewCharArray,
2269     checked_jni_NewShortArray,
2270     checked_jni_NewIntArray,
2271     checked_jni_NewLongArray,
2272     checked_jni_NewFloatArray,
2273     checked_jni_NewDoubleArray,
2274 
2275     checked_jni_GetBooleanArrayElements,
2276     checked_jni_GetByteArrayElements,
2277     checked_jni_GetCharArrayElements,
2278     checked_jni_GetShortArrayElements,
2279     checked_jni_GetIntArrayElements,
2280     checked_jni_GetLongArrayElements,
2281     checked_jni_GetFloatArrayElements,
2282     checked_jni_GetDoubleArrayElements,
2283 
2284     checked_jni_ReleaseBooleanArrayElements,
2285     checked_jni_ReleaseByteArrayElements,
2286     checked_jni_ReleaseCharArrayElements,
2287     checked_jni_ReleaseShortArrayElements,
2288     checked_jni_ReleaseIntArrayElements,
2289     checked_jni_ReleaseLongArrayElements,
2290     checked_jni_ReleaseFloatArrayElements,
2291     checked_jni_ReleaseDoubleArrayElements,
2292 
2293     checked_jni_GetBooleanArrayRegion,
2294     checked_jni_GetByteArrayRegion,
2295     checked_jni_GetCharArrayRegion,
2296     checked_jni_GetShortArrayRegion,
2297     checked_jni_GetIntArrayRegion,
2298     checked_jni_GetLongArrayRegion,
2299     checked_jni_GetFloatArrayRegion,
2300     checked_jni_GetDoubleArrayRegion,
2301 
2302     checked_jni_SetBooleanArrayRegion,
2303     checked_jni_SetByteArrayRegion,
2304     checked_jni_SetCharArrayRegion,
2305     checked_jni_SetShortArrayRegion,
2306     checked_jni_SetIntArrayRegion,
2307     checked_jni_SetLongArrayRegion,
2308     checked_jni_SetFloatArrayRegion,
2309     checked_jni_SetDoubleArrayRegion,
2310 
2311     checked_jni_RegisterNatives,
2312     checked_jni_UnregisterNatives,
2313 
2314     checked_jni_MonitorEnter,
2315     checked_jni_MonitorExit,
2316 
2317     checked_jni_GetJavaVM,
2318 
2319     checked_jni_GetStringRegion,
2320     checked_jni_GetStringUTFRegion,
2321 
2322     checked_jni_GetPrimitiveArrayCritical,
2323     checked_jni_ReleasePrimitiveArrayCritical,
2324 
2325     checked_jni_GetStringCritical,
2326     checked_jni_ReleaseStringCritical,
2327 
2328     checked_jni_NewWeakGlobalRef,
2329     checked_jni_DeleteWeakGlobalRef,
2330 
2331     checked_jni_ExceptionCheck,
2332 
2333     checked_jni_NewDirectByteBuffer,
2334     checked_jni_GetDirectBufferAddress,
2335     checked_jni_GetDirectBufferCapacity,
2336 
2337     // New 1.6 Features
2338 
2339     checked_jni_GetObjectRefType,
2340 
2341     // Module Features
2342 
2343     checked_jni_GetModule,
2344 
2345     // Virtual threads
2346 
2347     checked_jni_IsVirtualThread,
2348 
2349     // Large UTF8 support
2350 
2351     checked_jni_GetStringUTFLengthAsLong
2352 
2353 };
2354 
2355 
2356 // Returns the function structure
2357 struct JNINativeInterface_* jni_functions_check() {
2358 
2359   unchecked_jni_NativeInterface = jni_functions_nocheck();
2360 
2361   // make sure the last pointer in the checked table is not null, indicating
2362   // an addition to the JNINativeInterface_ structure without initializing
2363   // it in the checked table.
2364   DEBUG_ONLY(intptr_t *lastPtr = (intptr_t *)((char *)&checked_jni_NativeInterface + \
2365              sizeof(*unchecked_jni_NativeInterface) - sizeof(char *));)
2366   assert(*lastPtr != 0,
2367          "Mismatched JNINativeInterface tables, check for new entries");
2368 
2369   // with -verbose:jni this message will print
2370   log_debug(jni, resolve)("Checked JNI functions are being used to validate JNI usage");
2371 
2372   return &checked_jni_NativeInterface;
2373 }