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))
|