src/share/vm/prims/jniCheck.cpp

Print this page
rev 6560 : 6311046: -Xcheck:jni should support checking of GetPrimitiveArrayCritical.
Summary: Wrapped memory with standard bounds checking "GuardedMemory".
Reviewed-by: zgu, fparain, dcubed


   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 "precompiled.hpp"
  26 #include "classfile/systemDictionary.hpp"
  27 #include "classfile/vmSymbols.hpp"

  28 #include "oops/instanceKlass.hpp"
  29 #include "oops/oop.inline.hpp"
  30 #include "oops/symbol.hpp"
  31 #include "prims/jni.h"
  32 #include "prims/jniCheck.hpp"
  33 #include "prims/jvm_misc.hpp"
  34 #include "runtime/fieldDescriptor.hpp"
  35 #include "runtime/handles.hpp"
  36 #include "runtime/interfaceSupport.hpp"
  37 #include "runtime/jfieldIDWorkaround.hpp"
  38 #include "runtime/thread.inline.hpp"
  39 #ifdef TARGET_ARCH_x86
  40 # include "jniTypes_x86.hpp"
  41 #endif
  42 #ifdef TARGET_ARCH_sparc
  43 # include "jniTypes_sparc.hpp"
  44 #endif
  45 #ifdef TARGET_ARCH_zero
  46 # include "jniTypes_zero.hpp"
  47 #endif


 306 check_primitive_array_type(JavaThread* thr, jarray jArray, BasicType elementType)
 307 {
 308   BasicType array_type;
 309   arrayOop aOop;
 310 
 311   aOop = check_is_primitive_array(thr, jArray);
 312   array_type = TypeArrayKlass::cast(aOop->klass())->element_type();
 313   if (array_type != elementType) {
 314     ReportJNIFatalError(thr, fatal_element_type_mismatch);
 315   }
 316 }
 317 
 318 static inline void
 319 check_is_obj_array(JavaThread* thr, jarray jArray) {
 320   arrayOop aOop = check_is_array(thr, jArray);
 321   if (!aOop->is_objArray()) {
 322     ReportJNIFatalError(thr, fatal_object_array_expected);
 323   }
 324 }
 325 




































































 326 oop jniCheck::validate_handle(JavaThread* thr, jobject obj) {
 327   if (JNIHandles::is_frame_handle(thr, obj) ||
 328       JNIHandles::is_local_handle(thr, obj) ||
 329       JNIHandles::is_global_handle(obj) ||
 330       JNIHandles::is_weak_global_handle(obj)) {
 331     ASSERT_OOPS_ALLOWED;
 332     return JNIHandles::resolve_external_guard(obj);
 333   }
 334   ReportJNIFatalError(thr, fatal_bad_ref_to_jni);
 335   return NULL;
 336 }
 337 
 338 
 339 Method* jniCheck::validate_jmethod_id(JavaThread* thr, jmethodID method_id) {
 340   ASSERT_OOPS_ALLOWED;
 341   // do the fast jmethodID check first
 342   Method* moop = Method::checked_resolve_jmethod_id(method_id);
 343   if (moop == NULL) {
 344     ReportJNIFatalError(thr, fatal_wrong_class_or_method);
 345   }


1297                         jsize len))
1298     functionEnter(thr);
1299     jstring result = UNCHECKED()->NewString(env,unicode,len);
1300     functionExit(env);
1301     return result;
1302 JNI_END
1303 
1304 JNI_ENTRY_CHECKED(jsize,
1305   checked_jni_GetStringLength(JNIEnv *env,
1306                               jstring str))
1307     functionEnter(thr);
1308     IN_VM(
1309       checkString(thr, str);
1310     )
1311     jsize result = UNCHECKED()->GetStringLength(env,str);
1312     functionExit(env);
1313     return result;
1314 JNI_END
1315 
1316 // Arbitrary (but well-known) tag
1317 const jint STRING_TAG = 0x47114711;
1318 
1319 JNI_ENTRY_CHECKED(const jchar *,
1320   checked_jni_GetStringChars(JNIEnv *env,
1321                              jstring str,
1322                              jboolean *isCopy))
1323     functionEnter(thr);
1324     IN_VM(
1325       checkString(thr, str);
1326     )
1327     jchar* newResult = NULL;
1328     const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
1329     assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
1330     if (result != NULL) {
1331       size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
1332       jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), mtInternal);
1333       *tagLocation = STRING_TAG;
1334       newResult = (jchar*) (tagLocation + 1);
1335       memcpy(newResult, result, len * sizeof(jchar));

1336       // Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes
1337       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
1338       FreeHeap((char*)result);
1339     }
1340     functionExit(env);
1341     return newResult;
1342 JNI_END
1343 
1344 JNI_ENTRY_CHECKED(void,
1345   checked_jni_ReleaseStringChars(JNIEnv *env,
1346                                  jstring str,
1347                                  const jchar *chars))
1348     functionEnterExceptionAllowed(thr);
1349     IN_VM(
1350       checkString(thr, str);
1351     )
1352     if (chars == NULL) {
1353        // still do the unchecked call to allow dtrace probes
1354        UNCHECKED()->ReleaseStringChars(env,str,chars);
1355     }
1356     else {
1357        jint* tagLocation = ((jint*) chars) - 1;
1358        if (*tagLocation != STRING_TAG) {
1359           NativeReportJNIFatalError(thr, "ReleaseStringChars called on something not allocated by GetStringChars");











1360        }
1361        UNCHECKED()->ReleaseStringChars(env,str,(const jchar*)tagLocation);

1362     }
1363     functionExit(env);
1364 JNI_END
1365 
1366 JNI_ENTRY_CHECKED(jstring,
1367   checked_jni_NewStringUTF(JNIEnv *env,
1368                            const char *utf))
1369     functionEnter(thr);
1370     jstring result = UNCHECKED()->NewStringUTF(env,utf);
1371     functionExit(env);
1372     return result;
1373 JNI_END
1374 
1375 JNI_ENTRY_CHECKED(jsize,
1376   checked_jni_GetStringUTFLength(JNIEnv *env,
1377                                  jstring str))
1378     functionEnter(thr);
1379     IN_VM(
1380       checkString(thr, str);
1381     )
1382     jsize result = UNCHECKED()->GetStringUTFLength(env,str);
1383     functionExit(env);
1384     return result;
1385 JNI_END
1386 
1387 // Arbitrary (but well-known) tag - different than GetStringChars
1388 const jint STRING_UTF_TAG = 0x48124812;
1389 
1390 JNI_ENTRY_CHECKED(const char *,
1391   checked_jni_GetStringUTFChars(JNIEnv *env,
1392                                 jstring str,
1393                                 jboolean *isCopy))
1394     functionEnter(thr);
1395     IN_VM(
1396       checkString(thr, str);
1397     )
1398     char* newResult = NULL;
1399     const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
1400     assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
1401     if (result != NULL) {
1402       size_t len = strlen(result) + 1; // + 1 for NULL termination
1403       jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), mtInternal);
1404       *tagLocation = STRING_UTF_TAG;
1405       newResult = (char*) (tagLocation + 1);
1406       strcpy(newResult, result);
1407       // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
1408       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
1409       FreeHeap((char*)result, mtInternal);
1410     }
1411     functionExit(env);
1412     return newResult;
1413 JNI_END
1414 
1415 JNI_ENTRY_CHECKED(void,
1416   checked_jni_ReleaseStringUTFChars(JNIEnv *env,
1417                                     jstring str,
1418                                     const char* chars))
1419     functionEnterExceptionAllowed(thr);
1420     IN_VM(
1421       checkString(thr, str);
1422     )
1423     if (chars == NULL) {
1424        // still do the unchecked call to allow dtrace probes
1425        UNCHECKED()->ReleaseStringUTFChars(env,str,chars);
1426     }
1427     else {
1428        jint* tagLocation = ((jint*) chars) - 1;
1429        if (*tagLocation != STRING_UTF_TAG) {
1430           NativeReportJNIFatalError(thr, "ReleaseStringUTFChars called on something not allocated by GetStringUTFChars");











1431        }
1432        UNCHECKED()->ReleaseStringUTFChars(env,str,(const char*)tagLocation);

1433     }
1434     functionExit(env);
1435 JNI_END
1436 
1437 JNI_ENTRY_CHECKED(jsize,
1438   checked_jni_GetArrayLength(JNIEnv *env,
1439                              jarray array))
1440     functionEnter(thr);
1441     IN_VM(
1442       check_is_array(thr, array);
1443     )
1444     jsize result = UNCHECKED()->GetArrayLength(env,array);
1445     functionExit(env);
1446     return result;
1447 JNI_END
1448 
1449 JNI_ENTRY_CHECKED(jobjectArray,
1450   checked_jni_NewObjectArray(JNIEnv *env,
1451                              jsize len,
1452                              jclass clazz,


1497 WRAPPER_NewScalarArray(jbyteArray, Byte)
1498 WRAPPER_NewScalarArray(jshortArray, Short)
1499 WRAPPER_NewScalarArray(jcharArray, Char)
1500 WRAPPER_NewScalarArray(jintArray, Int)
1501 WRAPPER_NewScalarArray(jlongArray, Long)
1502 WRAPPER_NewScalarArray(jfloatArray, Float)
1503 WRAPPER_NewScalarArray(jdoubleArray, Double)
1504 
1505 #define WRAPPER_GetScalarArrayElements(ElementTag,ElementType,Result) \
1506 JNI_ENTRY_CHECKED(ElementType *,  \
1507   checked_jni_Get##Result##ArrayElements(JNIEnv *env, \
1508                                          ElementType##Array array, \
1509                                          jboolean *isCopy)) \
1510     functionEnter(thr); \
1511     IN_VM( \
1512       check_primitive_array_type(thr, array, ElementTag); \
1513     ) \
1514     ElementType *result = UNCHECKED()->Get##Result##ArrayElements(env, \
1515                                                                   array, \
1516                                                                   isCopy); \



1517     functionExit(env); \
1518     return result; \
1519 JNI_END
1520 
1521 WRAPPER_GetScalarArrayElements(T_BOOLEAN, jboolean, Boolean)
1522 WRAPPER_GetScalarArrayElements(T_BYTE,    jbyte,    Byte)
1523 WRAPPER_GetScalarArrayElements(T_SHORT,   jshort,   Short)
1524 WRAPPER_GetScalarArrayElements(T_CHAR,    jchar,    Char)
1525 WRAPPER_GetScalarArrayElements(T_INT,     jint,     Int)
1526 WRAPPER_GetScalarArrayElements(T_LONG,    jlong,    Long)
1527 WRAPPER_GetScalarArrayElements(T_FLOAT,   jfloat,   Float)
1528 WRAPPER_GetScalarArrayElements(T_DOUBLE,  jdouble,  Double)
1529 
1530 #define WRAPPER_ReleaseScalarArrayElements(ElementTag,ElementType,Result,Tag) \
1531 JNI_ENTRY_CHECKED(void,  \
1532   checked_jni_Release##Result##ArrayElements(JNIEnv *env, \
1533                                              ElementType##Array array, \
1534                                              ElementType *elems, \
1535                                              jint mode)) \
1536     functionEnterExceptionAllowed(thr); \
1537     IN_VM( \
1538       check_primitive_array_type(thr, array, ElementTag); \
1539       ASSERT_OOPS_ALLOWED; \
1540       typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
1541       /* cannot check validity of copy, unless every request is logged by
1542        * checking code.  Implementation of this check is deferred until a
1543        * subsequent release.
1544        */ \
1545     ) \
1546     UNCHECKED()->Release##Result##ArrayElements(env,array,elems,mode); \


1547     functionExit(env); \
1548 JNI_END
1549 
1550 WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool)
1551 WRAPPER_ReleaseScalarArrayElements(T_BYTE,   jbyte,    Byte,    byte)
1552 WRAPPER_ReleaseScalarArrayElements(T_SHORT,  jshort,   Short,   short)
1553 WRAPPER_ReleaseScalarArrayElements(T_CHAR,   jchar,    Char,    char)
1554 WRAPPER_ReleaseScalarArrayElements(T_INT,    jint,     Int,     int)
1555 WRAPPER_ReleaseScalarArrayElements(T_LONG,   jlong,    Long,    long)
1556 WRAPPER_ReleaseScalarArrayElements(T_FLOAT,  jfloat,   Float,   float)
1557 WRAPPER_ReleaseScalarArrayElements(T_DOUBLE, jdouble,  Double,  double)
1558 
1559 #define WRAPPER_GetScalarArrayRegion(ElementTag,ElementType,Result) \
1560 JNI_ENTRY_CHECKED(void,  \
1561   checked_jni_Get##Result##ArrayRegion(JNIEnv *env, \
1562                                        ElementType##Array array, \
1563                                        jsize start, \
1564                                        jsize len, \
1565                                        ElementType *buf)) \
1566     functionEnter(thr); \


1677                                  jsize start,
1678                                  jsize len,
1679                                  char *buf))
1680     functionEnter(thr);
1681     IN_VM(
1682       checkString(thr, str);
1683     )
1684     UNCHECKED()->GetStringUTFRegion(env, str, start, len, buf);
1685     functionExit(env);
1686 JNI_END
1687 
1688 JNI_ENTRY_CHECKED(void *,
1689   checked_jni_GetPrimitiveArrayCritical(JNIEnv *env,
1690                                         jarray array,
1691                                         jboolean *isCopy))
1692     functionEnterCritical(thr);
1693     IN_VM(
1694       check_is_primitive_array(thr, array);
1695     )
1696     void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy);



1697     functionExit(env);
1698     return result;
1699 JNI_END
1700 
1701 JNI_ENTRY_CHECKED(void,
1702   checked_jni_ReleasePrimitiveArrayCritical(JNIEnv *env,
1703                                             jarray array,
1704                                             void *carray,
1705                                             jint mode))
1706     functionEnterCriticalExceptionAllowed(thr);
1707     IN_VM(
1708       check_is_primitive_array(thr, array);
1709     )
1710     /* The Hotspot JNI code does not use the parameters, so just check the
1711      * array parameter as a minor sanity check
1712      */
1713     UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1714     functionExit(env);
1715 JNI_END
1716 
1717 JNI_ENTRY_CHECKED(const jchar*,
1718   checked_jni_GetStringCritical(JNIEnv *env,
1719                                 jstring string,
1720                                 jboolean *isCopy))
1721     functionEnterCritical(thr);
1722     IN_VM(
1723       checkString(thr, string);
1724     )
1725     const jchar *result = UNCHECKED()->GetStringCritical(env, string, isCopy);
1726     functionExit(env);
1727     return result;
1728 JNI_END
1729 
1730 JNI_ENTRY_CHECKED(void,
1731   checked_jni_ReleaseStringCritical(JNIEnv *env,
1732                                     jstring str,
1733                                     const jchar *chars))




   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 "precompiled.hpp"
  26 #include "classfile/systemDictionary.hpp"
  27 #include "classfile/vmSymbols.hpp"
  28 #include "memory/guardedMemory.hpp"
  29 #include "oops/instanceKlass.hpp"
  30 #include "oops/oop.inline.hpp"
  31 #include "oops/symbol.hpp"
  32 #include "prims/jni.h"
  33 #include "prims/jniCheck.hpp"
  34 #include "prims/jvm_misc.hpp"
  35 #include "runtime/fieldDescriptor.hpp"
  36 #include "runtime/handles.hpp"
  37 #include "runtime/interfaceSupport.hpp"
  38 #include "runtime/jfieldIDWorkaround.hpp"
  39 #include "runtime/thread.inline.hpp"
  40 #ifdef TARGET_ARCH_x86
  41 # include "jniTypes_x86.hpp"
  42 #endif
  43 #ifdef TARGET_ARCH_sparc
  44 # include "jniTypes_sparc.hpp"
  45 #endif
  46 #ifdef TARGET_ARCH_zero
  47 # include "jniTypes_zero.hpp"
  48 #endif


 307 check_primitive_array_type(JavaThread* thr, jarray jArray, BasicType elementType)
 308 {
 309   BasicType array_type;
 310   arrayOop aOop;
 311 
 312   aOop = check_is_primitive_array(thr, jArray);
 313   array_type = TypeArrayKlass::cast(aOop->klass())->element_type();
 314   if (array_type != elementType) {
 315     ReportJNIFatalError(thr, fatal_element_type_mismatch);
 316   }
 317 }
 318 
 319 static inline void
 320 check_is_obj_array(JavaThread* thr, jarray jArray) {
 321   arrayOop aOop = check_is_array(thr, jArray);
 322   if (!aOop->is_objArray()) {
 323     ReportJNIFatalError(thr, fatal_object_array_expected);
 324   }
 325 }
 326 
 327 /*
 328  * Copy and wrap array elements for bounds checking.
 329  * Remember the original elements (GuardedMemory::get_tag())
 330  */
 331 static void* check_jni_wrap_copy_array(JavaThread* thr, jarray array,
 332     void* orig_elements) {
 333   void* result;
 334   IN_VM(
 335     oop a = JNIHandles::resolve_non_null(array);
 336     size_t len = arrayOop(a)->length() <<
 337         TypeArrayKlass::cast(a->klass())->log2_element_size();
 338     result = GuardedMemory::wrap_copy(orig_elements, len, orig_elements);
 339   )
 340   return result;
 341 }
 342 
 343 static void* check_wrapped_array(JavaThread* thr, const char* fn_name,
 344     void* obj, void* carray, size_t* rsz) {
 345   if (carray == NULL) {
 346     tty->print_cr("%s: elements vector NULL" PTR_FORMAT, fn_name, p2i(obj));
 347     NativeReportJNIFatalError(thr, "Elements vector NULL");
 348   }
 349   GuardedMemory guarded(carray);
 350   void* orig_result = guarded.get_tag();
 351   if (!guarded.verify_guards()) {
 352     tty->print_cr("ReleasePrimitiveArrayCritical: release array failed bounds "
 353         "check, incorrect pointer returned ? array: " PTR_FORMAT " carray: "
 354         PTR_FORMAT, p2i(obj), p2i(carray));
 355     guarded.print_on(tty);
 356     NativeReportJNIFatalError(thr, "ReleasePrimitiveArrayCritical: "
 357         "failed bounds check");
 358   }
 359   if (orig_result == NULL) {
 360     tty->print_cr("ReleasePrimitiveArrayCritical: unrecognized elements. array: "
 361         PTR_FORMAT " carray: " PTR_FORMAT, p2i(obj), p2i(carray));
 362     guarded.print_on(tty);
 363     NativeReportJNIFatalError(thr, "ReleasePrimitiveArrayCritical: "
 364         "unrecognized elements");
 365   }
 366   if (rsz != NULL) {
 367     *rsz = guarded.get_user_size();
 368   }
 369   return orig_result;
 370 }
 371 
 372 static void* check_wrapped_array_release(JavaThread* thr, const char* fn_name,
 373     void* obj, void* carray, jint mode) {
 374   size_t sz;
 375   void* orig_result = check_wrapped_array(thr, fn_name, obj, carray, &sz);
 376   switch (mode) {
 377   case 0:
 378     memcpy(orig_result, carray, sz);
 379     GuardedMemory::free_copy(carray);
 380     break;
 381   case JNI_COMMIT:
 382     memcpy(orig_result, carray, sz);
 383     break;
 384   case JNI_ABORT:
 385     GuardedMemory::free_copy(carray);
 386     break;
 387   default:
 388     tty->print_cr("%s: Unrecognized mode %i releasing array "
 389         PTR_FORMAT " elements " PTR_FORMAT, fn_name, mode, p2i(obj), p2i(carray));
 390     NativeReportJNIFatalError(thr, "Unrecognized array release mode");
 391   }
 392   return orig_result;
 393 }
 394 
 395 oop jniCheck::validate_handle(JavaThread* thr, jobject obj) {
 396   if (JNIHandles::is_frame_handle(thr, obj) ||
 397       JNIHandles::is_local_handle(thr, obj) ||
 398       JNIHandles::is_global_handle(obj) ||
 399       JNIHandles::is_weak_global_handle(obj)) {
 400     ASSERT_OOPS_ALLOWED;
 401     return JNIHandles::resolve_external_guard(obj);
 402   }
 403   ReportJNIFatalError(thr, fatal_bad_ref_to_jni);
 404   return NULL;
 405 }
 406 
 407 
 408 Method* jniCheck::validate_jmethod_id(JavaThread* thr, jmethodID method_id) {
 409   ASSERT_OOPS_ALLOWED;
 410   // do the fast jmethodID check first
 411   Method* moop = Method::checked_resolve_jmethod_id(method_id);
 412   if (moop == NULL) {
 413     ReportJNIFatalError(thr, fatal_wrong_class_or_method);
 414   }


1366                         jsize len))
1367     functionEnter(thr);
1368     jstring result = UNCHECKED()->NewString(env,unicode,len);
1369     functionExit(env);
1370     return result;
1371 JNI_END
1372 
1373 JNI_ENTRY_CHECKED(jsize,
1374   checked_jni_GetStringLength(JNIEnv *env,
1375                               jstring str))
1376     functionEnter(thr);
1377     IN_VM(
1378       checkString(thr, str);
1379     )
1380     jsize result = UNCHECKED()->GetStringLength(env,str);
1381     functionExit(env);
1382     return result;
1383 JNI_END
1384 
1385 // Arbitrary (but well-known) tag
1386 const void* STRING_TAG = (void*)0x47114711;
1387 
1388 JNI_ENTRY_CHECKED(const jchar *,
1389   checked_jni_GetStringChars(JNIEnv *env,
1390                              jstring str,
1391                              jboolean *isCopy))
1392     functionEnter(thr);
1393     IN_VM(
1394       checkString(thr, str);
1395     )
1396     jchar* new_result = NULL;
1397     const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
1398     assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
1399     if (result != NULL) {
1400       size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
1401       len *= sizeof(jchar);
1402       new_result = (jchar*) GuardedMemory::wrap_copy(result, len, STRING_TAG);
1403       if (new_result == NULL) {
1404         vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringChars");
1405       }
1406       // Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes
1407       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
1408       FreeHeap((char*)result);
1409     }
1410     functionExit(env);
1411     return new_result;
1412 JNI_END
1413 
1414 JNI_ENTRY_CHECKED(void,
1415   checked_jni_ReleaseStringChars(JNIEnv *env,
1416                                  jstring str,
1417                                  const jchar *chars))
1418     functionEnterExceptionAllowed(thr);
1419     IN_VM(
1420       checkString(thr, str);
1421     )
1422     if (chars == NULL) {
1423        // still do the unchecked call to allow dtrace probes
1424        UNCHECKED()->ReleaseStringChars(env,str,chars);
1425     }
1426     else {
1427       GuardedMemory guarded((void*)chars);
1428       if (guarded.verify_guards()) {
1429         tty->print_cr("ReleaseStringChars: release chars failed bounds check. "
1430             "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars));
1431         guarded.print_on(tty);
1432         NativeReportJNIFatalError(thr, "ReleaseStringChars: "
1433             "release chars failed bounds check.");
1434       }
1435       if (guarded.get_tag() != STRING_TAG) {
1436         tty->print_cr("ReleaseStringChars: called on something not allocated "
1437             "by GetStringChars. string: " PTR_FORMAT " chars: " PTR_FORMAT,
1438             p2i(str), p2i(chars));
1439         NativeReportJNIFatalError(thr, "ReleaseStringChars called on something "
1440             "not allocated by GetStringChars");
1441       }
1442        UNCHECKED()->ReleaseStringChars(env, str,
1443            (const jchar*) guarded.release_for_freeing());
1444     }
1445     functionExit(env);
1446 JNI_END
1447 
1448 JNI_ENTRY_CHECKED(jstring,
1449   checked_jni_NewStringUTF(JNIEnv *env,
1450                            const char *utf))
1451     functionEnter(thr);
1452     jstring result = UNCHECKED()->NewStringUTF(env,utf);
1453     functionExit(env);
1454     return result;
1455 JNI_END
1456 
1457 JNI_ENTRY_CHECKED(jsize,
1458   checked_jni_GetStringUTFLength(JNIEnv *env,
1459                                  jstring str))
1460     functionEnter(thr);
1461     IN_VM(
1462       checkString(thr, str);
1463     )
1464     jsize result = UNCHECKED()->GetStringUTFLength(env,str);
1465     functionExit(env);
1466     return result;
1467 JNI_END
1468 
1469 // Arbitrary (but well-known) tag - different than GetStringChars
1470 const void* STRING_UTF_TAG = (void*) 0x48124812;
1471 
1472 JNI_ENTRY_CHECKED(const char *,
1473   checked_jni_GetStringUTFChars(JNIEnv *env,
1474                                 jstring str,
1475                                 jboolean *isCopy))
1476     functionEnter(thr);
1477     IN_VM(
1478       checkString(thr, str);
1479     )
1480     char* new_result = NULL;
1481     const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
1482     assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
1483     if (result != NULL) {
1484       size_t len = strlen(result) + 1; // + 1 for NULL termination
1485       new_result = (char*) GuardedMemory::wrap_copy(result, len, STRING_UTF_TAG);
1486       if (new_result == NULL) {
1487         vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringUTFChars");
1488       }
1489       // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
1490       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
1491       FreeHeap((char*)result, mtInternal);
1492     }
1493     functionExit(env);
1494     return new_result;
1495 JNI_END
1496 
1497 JNI_ENTRY_CHECKED(void,
1498   checked_jni_ReleaseStringUTFChars(JNIEnv *env,
1499                                     jstring str,
1500                                     const char* chars))
1501     functionEnterExceptionAllowed(thr);
1502     IN_VM(
1503       checkString(thr, str);
1504     )
1505     if (chars == NULL) {
1506        // still do the unchecked call to allow dtrace probes
1507        UNCHECKED()->ReleaseStringUTFChars(env,str,chars);
1508     }
1509     else {
1510       GuardedMemory guarded((void*)chars);
1511       if (guarded.verify_guards()) {
1512         tty->print_cr("ReleaseStringUTFChars: release chars failed bounds check. "
1513             "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars));
1514         guarded.print_on(tty);
1515         NativeReportJNIFatalError(thr, "ReleaseStringUTFChars: "
1516             "release chars failed bounds check.");
1517       }
1518       if (guarded.get_tag() != STRING_UTF_TAG) {
1519         tty->print_cr("ReleaseStringUTFChars: called on something not "
1520             "allocated by GetStringUTFChars. string: " PTR_FORMAT " chars: "
1521             PTR_FORMAT, p2i(str), p2i(chars));
1522         NativeReportJNIFatalError(thr, "ReleaseStringUTFChars "
1523             "called on something not allocated by GetStringUTFChars");
1524       }
1525       UNCHECKED()->ReleaseStringUTFChars(env, str,
1526           (const char*) guarded.release_for_freeing());
1527     }
1528     functionExit(env);
1529 JNI_END
1530 
1531 JNI_ENTRY_CHECKED(jsize,
1532   checked_jni_GetArrayLength(JNIEnv *env,
1533                              jarray array))
1534     functionEnter(thr);
1535     IN_VM(
1536       check_is_array(thr, array);
1537     )
1538     jsize result = UNCHECKED()->GetArrayLength(env,array);
1539     functionExit(env);
1540     return result;
1541 JNI_END
1542 
1543 JNI_ENTRY_CHECKED(jobjectArray,
1544   checked_jni_NewObjectArray(JNIEnv *env,
1545                              jsize len,
1546                              jclass clazz,


1591 WRAPPER_NewScalarArray(jbyteArray, Byte)
1592 WRAPPER_NewScalarArray(jshortArray, Short)
1593 WRAPPER_NewScalarArray(jcharArray, Char)
1594 WRAPPER_NewScalarArray(jintArray, Int)
1595 WRAPPER_NewScalarArray(jlongArray, Long)
1596 WRAPPER_NewScalarArray(jfloatArray, Float)
1597 WRAPPER_NewScalarArray(jdoubleArray, Double)
1598 
1599 #define WRAPPER_GetScalarArrayElements(ElementTag,ElementType,Result) \
1600 JNI_ENTRY_CHECKED(ElementType *,  \
1601   checked_jni_Get##Result##ArrayElements(JNIEnv *env, \
1602                                          ElementType##Array array, \
1603                                          jboolean *isCopy)) \
1604     functionEnter(thr); \
1605     IN_VM( \
1606       check_primitive_array_type(thr, array, ElementTag); \
1607     ) \
1608     ElementType *result = UNCHECKED()->Get##Result##ArrayElements(env, \
1609                                                                   array, \
1610                                                                   isCopy); \
1611     if (result != NULL) { \
1612       result = (ElementType *) check_jni_wrap_copy_array(thr, array, result); \
1613     } \
1614     functionExit(env); \
1615     return result; \
1616 JNI_END
1617 
1618 WRAPPER_GetScalarArrayElements(T_BOOLEAN, jboolean, Boolean)
1619 WRAPPER_GetScalarArrayElements(T_BYTE,    jbyte,    Byte)
1620 WRAPPER_GetScalarArrayElements(T_SHORT,   jshort,   Short)
1621 WRAPPER_GetScalarArrayElements(T_CHAR,    jchar,    Char)
1622 WRAPPER_GetScalarArrayElements(T_INT,     jint,     Int)
1623 WRAPPER_GetScalarArrayElements(T_LONG,    jlong,    Long)
1624 WRAPPER_GetScalarArrayElements(T_FLOAT,   jfloat,   Float)
1625 WRAPPER_GetScalarArrayElements(T_DOUBLE,  jdouble,  Double)
1626 
1627 #define WRAPPER_ReleaseScalarArrayElements(ElementTag,ElementType,Result,Tag) \
1628 JNI_ENTRY_CHECKED(void,  \
1629   checked_jni_Release##Result##ArrayElements(JNIEnv *env, \
1630                                              ElementType##Array array, \
1631                                              ElementType *elems, \
1632                                              jint mode)) \
1633     functionEnterExceptionAllowed(thr); \
1634     IN_VM( \
1635       check_primitive_array_type(thr, array, ElementTag); \
1636       ASSERT_OOPS_ALLOWED; \
1637       typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \




1638     ) \
1639     ElementType* orig_result = (ElementType *) check_wrapped_array_release( \
1640         thr, "checked_jni_Release"#Result"ArrayElements", array, elems, mode); \
1641     UNCHECKED()->Release##Result##ArrayElements(env, array, orig_result, mode); \
1642     functionExit(env); \
1643 JNI_END
1644 
1645 WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool)
1646 WRAPPER_ReleaseScalarArrayElements(T_BYTE,   jbyte,    Byte,    byte)
1647 WRAPPER_ReleaseScalarArrayElements(T_SHORT,  jshort,   Short,   short)
1648 WRAPPER_ReleaseScalarArrayElements(T_CHAR,   jchar,    Char,    char)
1649 WRAPPER_ReleaseScalarArrayElements(T_INT,    jint,     Int,     int)
1650 WRAPPER_ReleaseScalarArrayElements(T_LONG,   jlong,    Long,    long)
1651 WRAPPER_ReleaseScalarArrayElements(T_FLOAT,  jfloat,   Float,   float)
1652 WRAPPER_ReleaseScalarArrayElements(T_DOUBLE, jdouble,  Double,  double)
1653 
1654 #define WRAPPER_GetScalarArrayRegion(ElementTag,ElementType,Result) \
1655 JNI_ENTRY_CHECKED(void,  \
1656   checked_jni_Get##Result##ArrayRegion(JNIEnv *env, \
1657                                        ElementType##Array array, \
1658                                        jsize start, \
1659                                        jsize len, \
1660                                        ElementType *buf)) \
1661     functionEnter(thr); \


1772                                  jsize start,
1773                                  jsize len,
1774                                  char *buf))
1775     functionEnter(thr);
1776     IN_VM(
1777       checkString(thr, str);
1778     )
1779     UNCHECKED()->GetStringUTFRegion(env, str, start, len, buf);
1780     functionExit(env);
1781 JNI_END
1782 
1783 JNI_ENTRY_CHECKED(void *,
1784   checked_jni_GetPrimitiveArrayCritical(JNIEnv *env,
1785                                         jarray array,
1786                                         jboolean *isCopy))
1787     functionEnterCritical(thr);
1788     IN_VM(
1789       check_is_primitive_array(thr, array);
1790     )
1791     void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy);
1792     if (result != NULL) {
1793       result = check_jni_wrap_copy_array(thr, array, result);
1794     }
1795     functionExit(env);
1796     return result;
1797 JNI_END
1798 
1799 JNI_ENTRY_CHECKED(void,
1800   checked_jni_ReleasePrimitiveArrayCritical(JNIEnv *env,
1801                                             jarray array,
1802                                             void *carray,
1803                                             jint mode))
1804     functionEnterCriticalExceptionAllowed(thr);
1805     IN_VM(
1806       check_is_primitive_array(thr, array);
1807     )
1808     // Check the element array...
1809     void* orig_result = check_wrapped_array_release(thr, "ReleasePrimitiveArrayCritical", array, carray, mode);
1810     UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, orig_result, mode);

1811     functionExit(env);
1812 JNI_END
1813 
1814 JNI_ENTRY_CHECKED(const jchar*,
1815   checked_jni_GetStringCritical(JNIEnv *env,
1816                                 jstring string,
1817                                 jboolean *isCopy))
1818     functionEnterCritical(thr);
1819     IN_VM(
1820       checkString(thr, string);
1821     )
1822     const jchar *result = UNCHECKED()->GetStringCritical(env, string, isCopy);
1823     functionExit(env);
1824     return result;
1825 JNI_END
1826 
1827 JNI_ENTRY_CHECKED(void,
1828   checked_jni_ReleaseStringCritical(JNIEnv *env,
1829                                     jstring str,
1830                                     const jchar *chars))