src/share/vm/prims/jniCheck.cpp

Print this page
rev 6359 : 6311046: -Xcheck:jni should support checking of GetPrimitiveArrayCritical
Summary: Unified memory bounds checking, introducted to checked JNI.
Reviewed-by: rbackman


   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.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/fencedMemory.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.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 (FencedMemory::get_tag())
 330  */
 331 static void* check_jni_wrap_copy_array(JavaThread* thr, jarray array, void* orig_elements) {
 332   void* result;
 333   IN_VM(
 334     oop a = JNIHandles::resolve_non_null(array);
 335     size_t len = arrayOop(a)->length() << TypeArrayKlass::cast(a->klass())->log2_element_size();
 336     result = FencedMemory::wrap_copy(orig_elements, len, orig_elements);
 337   )
 338   return result;
 339 }
 340 
 341 static void* check_wrapped_array(JavaThread* thr, const char* fn_name, void* obj, void* carray, size_t* rsz) {
 342   if (carray == NULL) {
 343     tty->print_cr("%s: elements vector NULL" PTR_FORMAT, fn_name, obj);
 344     NativeReportJNIFatalError(thr, "Elements vector NULL");
 345   }
 346   FencedMemory fenced(carray);
 347   void* orig_result = fenced.get_tag();
 348   if ((!fenced.verify_fences()) || (orig_result == NULL)) {
 349     tty->print_cr("ReleasePrimitiveArrayCritical: unrecognized elements"
 350         PTR_FORMAT " elements " PTR_FORMAT, obj, carray);
 351     fenced.print_on(tty);
 352     NativeReportJNIFatalError(thr, "Unrecognized elements");
 353   }
 354   if (rsz != NULL) {
 355     *rsz = fenced.get_user_size();
 356   }
 357   return orig_result;
 358 }
 359 
 360 static void* check_wrapped_array_release(JavaThread* thr, const char* fn_name, void* obj, void* carray, jint mode) {
 361   size_t sz;
 362   void* orig_result = check_wrapped_array(thr, fn_name, obj, carray, &sz);
 363   switch (mode) {
 364   case 0:
 365     memcpy(orig_result, carray, sz);
 366     FencedMemory::free_copy(carray);
 367     break;
 368   case JNI_COMMIT:
 369     memcpy(orig_result, carray, sz);
 370     break;
 371   case JNI_ABORT:
 372     FencedMemory::free_copy(carray);
 373     break;
 374   default:
 375     tty->print_cr("%s: Unrecognized mode %i releasing array "
 376         PTR_FORMAT " elements " PTR_FORMAT, fn_name, mode, obj, carray);
 377     NativeReportJNIFatalError(thr, "Unrecognized array release mode");
 378   }
 379   return orig_result;
 380 }
 381 
 382 oop jniCheck::validate_handle(JavaThread* thr, jobject obj) {
 383   if (JNIHandles::is_frame_handle(thr, obj) ||
 384       JNIHandles::is_local_handle(thr, obj) ||
 385       JNIHandles::is_global_handle(obj) ||
 386       JNIHandles::is_weak_global_handle(obj)) {
 387     ASSERT_OOPS_ALLOWED;
 388     return JNIHandles::resolve_external_guard(obj);
 389   }
 390   ReportJNIFatalError(thr, fatal_bad_ref_to_jni);
 391   return NULL;
 392 }
 393 
 394 
 395 Method* jniCheck::validate_jmethod_id(JavaThread* thr, jmethodID method_id) {
 396   ASSERT_OOPS_ALLOWED;
 397   // do the fast jmethodID check first
 398   Method* moop = Method::checked_resolve_jmethod_id(method_id);
 399   if (moop == NULL) {
 400     ReportJNIFatalError(thr, fatal_wrong_class_or_method);
 401   }


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


1554 WRAPPER_NewScalarArray(jbyteArray, Byte)
1555 WRAPPER_NewScalarArray(jshortArray, Short)
1556 WRAPPER_NewScalarArray(jcharArray, Char)
1557 WRAPPER_NewScalarArray(jintArray, Int)
1558 WRAPPER_NewScalarArray(jlongArray, Long)
1559 WRAPPER_NewScalarArray(jfloatArray, Float)
1560 WRAPPER_NewScalarArray(jdoubleArray, Double)
1561 
1562 #define WRAPPER_GetScalarArrayElements(ElementTag,ElementType,Result) \
1563 JNI_ENTRY_CHECKED(ElementType *,  \
1564   checked_jni_Get##Result##ArrayElements(JNIEnv *env, \
1565                                          ElementType##Array array, \
1566                                          jboolean *isCopy)) \
1567     functionEnter(thr); \
1568     IN_VM( \
1569       check_primitive_array_type(thr, array, ElementTag); \
1570     ) \
1571     ElementType *result = UNCHECKED()->Get##Result##ArrayElements(env, \
1572                                                                   array, \
1573                                                                   isCopy); \
1574     if (result != NULL) { \
1575       result = (ElementType *) check_jni_wrap_copy_array(thr, array, result); \
1576     } \
1577     functionExit(env); \
1578     return result; \
1579 JNI_END
1580 
1581 WRAPPER_GetScalarArrayElements(T_BOOLEAN, jboolean, Boolean)
1582 WRAPPER_GetScalarArrayElements(T_BYTE,    jbyte,    Byte)
1583 WRAPPER_GetScalarArrayElements(T_SHORT,   jshort,   Short)
1584 WRAPPER_GetScalarArrayElements(T_CHAR,    jchar,    Char)
1585 WRAPPER_GetScalarArrayElements(T_INT,     jint,     Int)
1586 WRAPPER_GetScalarArrayElements(T_LONG,    jlong,    Long)
1587 WRAPPER_GetScalarArrayElements(T_FLOAT,   jfloat,   Float)
1588 WRAPPER_GetScalarArrayElements(T_DOUBLE,  jdouble,  Double)
1589 
1590 #define WRAPPER_ReleaseScalarArrayElements(ElementTag,ElementType,Result,Tag) \
1591 JNI_ENTRY_CHECKED(void,  \
1592   checked_jni_Release##Result##ArrayElements(JNIEnv *env, \
1593                                              ElementType##Array array, \
1594                                              ElementType *elems, \
1595                                              jint mode)) \
1596     functionEnterExceptionAllowed(thr); \
1597     IN_VM( \
1598       check_primitive_array_type(thr, array, ElementTag); \
1599       ASSERT_OOPS_ALLOWED; \
1600       typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \




1601     ) \
1602     ElementType* orig_result = (ElementType *) check_wrapped_array_release( \
1603         thr, "checked_jni_Release"#Result"ArrayElements", array, elems, mode); \
1604     UNCHECKED()->Release##Result##ArrayElements(env,array,orig_result,mode); \
1605     functionExit(env); \
1606 JNI_END
1607 
1608 WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool)
1609 WRAPPER_ReleaseScalarArrayElements(T_BYTE,   jbyte,    Byte,    byte)
1610 WRAPPER_ReleaseScalarArrayElements(T_SHORT,  jshort,   Short,   short)
1611 WRAPPER_ReleaseScalarArrayElements(T_CHAR,   jchar,    Char,    char)
1612 WRAPPER_ReleaseScalarArrayElements(T_INT,    jint,     Int,     int)
1613 WRAPPER_ReleaseScalarArrayElements(T_LONG,   jlong,    Long,    long)
1614 WRAPPER_ReleaseScalarArrayElements(T_FLOAT,  jfloat,   Float,   float)
1615 WRAPPER_ReleaseScalarArrayElements(T_DOUBLE, jdouble,  Double,  double)
1616 
1617 #define WRAPPER_GetScalarArrayRegion(ElementTag,ElementType,Result) \
1618 JNI_ENTRY_CHECKED(void,  \
1619   checked_jni_Get##Result##ArrayRegion(JNIEnv *env, \
1620                                        ElementType##Array array, \
1621                                        jsize start, \
1622                                        jsize len, \
1623                                        ElementType *buf)) \
1624     functionEnter(thr); \


1735                                  jsize start,
1736                                  jsize len,
1737                                  char *buf))
1738     functionEnter(thr);
1739     IN_VM(
1740       checkString(thr, str);
1741     )
1742     UNCHECKED()->GetStringUTFRegion(env, str, start, len, buf);
1743     functionExit(env);
1744 JNI_END
1745 
1746 JNI_ENTRY_CHECKED(void *,
1747   checked_jni_GetPrimitiveArrayCritical(JNIEnv *env,
1748                                         jarray array,
1749                                         jboolean *isCopy))
1750     functionEnterCritical(thr);
1751     IN_VM(
1752       check_is_primitive_array(thr, array);
1753     )
1754     void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy);
1755     if (result != NULL) {
1756       result = check_jni_wrap_copy_array(thr, array, result);
1757     }
1758     functionExit(env);
1759     return result;
1760 JNI_END
1761 
1762 JNI_ENTRY_CHECKED(void,
1763   checked_jni_ReleasePrimitiveArrayCritical(JNIEnv *env,
1764                                             jarray array,
1765                                             void *carray,
1766                                             jint mode))
1767     functionEnterCriticalExceptionAllowed(thr);
1768     IN_VM(
1769       check_is_primitive_array(thr, array);
1770     )
1771     // Check the element array...
1772     void* orig_result = check_wrapped_array_release(thr, "ReleasePrimitiveArrayCritical", array, carray, mode);
1773     UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, orig_result, mode);

1774     functionExit(env);
1775 JNI_END
1776 
1777 JNI_ENTRY_CHECKED(const jchar*,
1778   checked_jni_GetStringCritical(JNIEnv *env,
1779                                 jstring string,
1780                                 jboolean *isCopy))
1781     functionEnterCritical(thr);
1782     IN_VM(
1783       checkString(thr, string);
1784     )
1785     const jchar *result = UNCHECKED()->GetStringCritical(env, string, isCopy);
1786     functionExit(env);
1787     return result;
1788 JNI_END
1789 
1790 JNI_ENTRY_CHECKED(void,
1791   checked_jni_ReleaseStringCritical(JNIEnv *env,
1792                                     jstring str,
1793                                     const jchar *chars))