comparison src/share/vm/prims/jniCheck.cpp @ 20804:7848fc12602b

Merge with jdk8u40-b25
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Tue, 07 Apr 2015 14:58:49 +0200
parents 52b4284cb496 29a5c2fd2d2e
children
comparison
equal deleted inserted replaced
20184:84105dcdb05b 20804:7848fc12602b
23 */ 23 */
24 24
25 #include "precompiled.hpp" 25 #include "precompiled.hpp"
26 #include "classfile/systemDictionary.hpp" 26 #include "classfile/systemDictionary.hpp"
27 #include "classfile/vmSymbols.hpp" 27 #include "classfile/vmSymbols.hpp"
28 #include "memory/guardedMemory.hpp"
28 #include "oops/instanceKlass.hpp" 29 #include "oops/instanceKlass.hpp"
29 #include "oops/oop.inline.hpp" 30 #include "oops/oop.inline.hpp"
30 #include "oops/symbol.hpp" 31 #include "oops/symbol.hpp"
31 #include "prims/jni.h" 32 #include "prims/jni.h"
32 #include "prims/jniCheck.hpp" 33 #include "prims/jniCheck.hpp"
33 #include "prims/jvm_misc.hpp" 34 #include "prims/jvm_misc.hpp"
34 #include "runtime/fieldDescriptor.hpp" 35 #include "runtime/fieldDescriptor.hpp"
35 #include "runtime/handles.hpp" 36 #include "runtime/handles.hpp"
36 #include "runtime/interfaceSupport.hpp" 37 #include "runtime/interfaceSupport.hpp"
37 #include "runtime/jfieldIDWorkaround.hpp" 38 #include "runtime/jfieldIDWorkaround.hpp"
38 #include "runtime/thread.hpp" 39 #include "runtime/thread.inline.hpp"
39 #ifdef TARGET_ARCH_x86 40 #ifdef TARGET_ARCH_x86
40 # include "jniTypes_x86.hpp" 41 # include "jniTypes_x86.hpp"
41 #endif 42 #endif
42 #ifdef TARGET_ARCH_sparc 43 #ifdef TARGET_ARCH_sparc
43 # include "jniTypes_sparc.hpp" 44 # include "jniTypes_sparc.hpp"
319 check_is_obj_array(JavaThread* thr, jarray jArray) { 320 check_is_obj_array(JavaThread* thr, jarray jArray) {
320 arrayOop aOop = check_is_array(thr, jArray); 321 arrayOop aOop = check_is_array(thr, jArray);
321 if (!aOop->is_objArray()) { 322 if (!aOop->is_objArray()) {
322 ReportJNIFatalError(thr, fatal_object_array_expected); 323 ReportJNIFatalError(thr, fatal_object_array_expected);
323 } 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;
324 } 393 }
325 394
326 oop jniCheck::validate_handle(JavaThread* thr, jobject obj) { 395 oop jniCheck::validate_handle(JavaThread* thr, jobject obj) {
327 if (JNIHandles::is_frame_handle(thr, obj) || 396 if (JNIHandles::is_frame_handle(thr, obj) ||
328 JNIHandles::is_local_handle(thr, obj) || 397 JNIHandles::is_local_handle(thr, obj) ||
1312 functionExit(env); 1381 functionExit(env);
1313 return result; 1382 return result;
1314 JNI_END 1383 JNI_END
1315 1384
1316 // Arbitrary (but well-known) tag 1385 // Arbitrary (but well-known) tag
1317 const jint STRING_TAG = 0x47114711; 1386 const void* STRING_TAG = (void*)0x47114711;
1318 1387
1319 JNI_ENTRY_CHECKED(const jchar *, 1388 JNI_ENTRY_CHECKED(const jchar *,
1320 checked_jni_GetStringChars(JNIEnv *env, 1389 checked_jni_GetStringChars(JNIEnv *env,
1321 jstring str, 1390 jstring str,
1322 jboolean *isCopy)) 1391 jboolean *isCopy))
1323 functionEnter(thr); 1392 functionEnter(thr);
1324 IN_VM( 1393 IN_VM(
1325 checkString(thr, str); 1394 checkString(thr, str);
1326 ) 1395 )
1327 jchar* newResult = NULL; 1396 jchar* new_result = NULL;
1328 const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy); 1397 const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
1329 assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected"); 1398 assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
1330 if (result != NULL) { 1399 if (result != NULL) {
1331 size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination 1400 size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
1332 jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), mtInternal); 1401 len *= sizeof(jchar);
1333 *tagLocation = STRING_TAG; 1402 new_result = (jchar*) GuardedMemory::wrap_copy(result, len, STRING_TAG);
1334 newResult = (jchar*) (tagLocation + 1); 1403 if (new_result == NULL) {
1335 memcpy(newResult, result, len * sizeof(jchar)); 1404 vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringChars");
1405 }
1336 // Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes 1406 // 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. 1407 // Note that the dtrace arguments for the allocated memory will not match up with this solution.
1338 FreeHeap((char*)result); 1408 FreeHeap((char*)result);
1339 } 1409 }
1340 functionExit(env); 1410 functionExit(env);
1341 return newResult; 1411 return new_result;
1342 JNI_END 1412 JNI_END
1343 1413
1344 JNI_ENTRY_CHECKED(void, 1414 JNI_ENTRY_CHECKED(void,
1345 checked_jni_ReleaseStringChars(JNIEnv *env, 1415 checked_jni_ReleaseStringChars(JNIEnv *env,
1346 jstring str, 1416 jstring str,
1352 if (chars == NULL) { 1422 if (chars == NULL) {
1353 // still do the unchecked call to allow dtrace probes 1423 // still do the unchecked call to allow dtrace probes
1354 UNCHECKED()->ReleaseStringChars(env,str,chars); 1424 UNCHECKED()->ReleaseStringChars(env,str,chars);
1355 } 1425 }
1356 else { 1426 else {
1357 jint* tagLocation = ((jint*) chars) - 1; 1427 GuardedMemory guarded((void*)chars);
1358 if (*tagLocation != STRING_TAG) { 1428 if (!guarded.verify_guards()) {
1359 NativeReportJNIFatalError(thr, "ReleaseStringChars called on something not allocated by GetStringChars"); 1429 tty->print_cr("ReleaseStringChars: release chars failed bounds check. "
1360 } 1430 "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars));
1361 UNCHECKED()->ReleaseStringChars(env,str,(const jchar*)tagLocation); 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());
1362 } 1444 }
1363 functionExit(env); 1445 functionExit(env);
1364 JNI_END 1446 JNI_END
1365 1447
1366 JNI_ENTRY_CHECKED(jstring, 1448 JNI_ENTRY_CHECKED(jstring,
1383 functionExit(env); 1465 functionExit(env);
1384 return result; 1466 return result;
1385 JNI_END 1467 JNI_END
1386 1468
1387 // Arbitrary (but well-known) tag - different than GetStringChars 1469 // Arbitrary (but well-known) tag - different than GetStringChars
1388 const jint STRING_UTF_TAG = 0x48124812; 1470 const void* STRING_UTF_TAG = (void*) 0x48124812;
1389 1471
1390 JNI_ENTRY_CHECKED(const char *, 1472 JNI_ENTRY_CHECKED(const char *,
1391 checked_jni_GetStringUTFChars(JNIEnv *env, 1473 checked_jni_GetStringUTFChars(JNIEnv *env,
1392 jstring str, 1474 jstring str,
1393 jboolean *isCopy)) 1475 jboolean *isCopy))
1394 functionEnter(thr); 1476 functionEnter(thr);
1395 IN_VM( 1477 IN_VM(
1396 checkString(thr, str); 1478 checkString(thr, str);
1397 ) 1479 )
1398 char* newResult = NULL; 1480 char* new_result = NULL;
1399 const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy); 1481 const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
1400 assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected"); 1482 assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
1401 if (result != NULL) { 1483 if (result != NULL) {
1402 size_t len = strlen(result) + 1; // + 1 for NULL termination 1484 size_t len = strlen(result) + 1; // + 1 for NULL termination
1403 jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), mtInternal); 1485 new_result = (char*) GuardedMemory::wrap_copy(result, len, STRING_UTF_TAG);
1404 *tagLocation = STRING_UTF_TAG; 1486 if (new_result == NULL) {
1405 newResult = (char*) (tagLocation + 1); 1487 vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringUTFChars");
1406 strcpy(newResult, result); 1488 }
1407 // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes 1489 // 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. 1490 // Note that the dtrace arguments for the allocated memory will not match up with this solution.
1409 FreeHeap((char*)result, mtInternal); 1491 FreeHeap((char*)result, mtInternal);
1410 } 1492 }
1411 functionExit(env); 1493 functionExit(env);
1412 return newResult; 1494 return new_result;
1413 JNI_END 1495 JNI_END
1414 1496
1415 JNI_ENTRY_CHECKED(void, 1497 JNI_ENTRY_CHECKED(void,
1416 checked_jni_ReleaseStringUTFChars(JNIEnv *env, 1498 checked_jni_ReleaseStringUTFChars(JNIEnv *env,
1417 jstring str, 1499 jstring str,
1423 if (chars == NULL) { 1505 if (chars == NULL) {
1424 // still do the unchecked call to allow dtrace probes 1506 // still do the unchecked call to allow dtrace probes
1425 UNCHECKED()->ReleaseStringUTFChars(env,str,chars); 1507 UNCHECKED()->ReleaseStringUTFChars(env,str,chars);
1426 } 1508 }
1427 else { 1509 else {
1428 jint* tagLocation = ((jint*) chars) - 1; 1510 GuardedMemory guarded((void*)chars);
1429 if (*tagLocation != STRING_UTF_TAG) { 1511 if (!guarded.verify_guards()) {
1430 NativeReportJNIFatalError(thr, "ReleaseStringUTFChars called on something not allocated by GetStringUTFChars"); 1512 tty->print_cr("ReleaseStringUTFChars: release chars failed bounds check. "
1431 } 1513 "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars));
1432 UNCHECKED()->ReleaseStringUTFChars(env,str,(const char*)tagLocation); 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());
1433 } 1527 }
1434 functionExit(env); 1528 functionExit(env);
1435 JNI_END 1529 JNI_END
1436 1530
1437 JNI_ENTRY_CHECKED(jsize, 1531 JNI_ENTRY_CHECKED(jsize,
1512 check_primitive_array_type(thr, array, ElementTag); \ 1606 check_primitive_array_type(thr, array, ElementTag); \
1513 ) \ 1607 ) \
1514 ElementType *result = UNCHECKED()->Get##Result##ArrayElements(env, \ 1608 ElementType *result = UNCHECKED()->Get##Result##ArrayElements(env, \
1515 array, \ 1609 array, \
1516 isCopy); \ 1610 isCopy); \
1611 if (result != NULL) { \
1612 result = (ElementType *) check_jni_wrap_copy_array(thr, array, result); \
1613 } \
1517 functionExit(env); \ 1614 functionExit(env); \
1518 return result; \ 1615 return result; \
1519 JNI_END 1616 JNI_END
1520 1617
1521 WRAPPER_GetScalarArrayElements(T_BOOLEAN, jboolean, Boolean) 1618 WRAPPER_GetScalarArrayElements(T_BOOLEAN, jboolean, Boolean)
1536 functionEnterExceptionAllowed(thr); \ 1633 functionEnterExceptionAllowed(thr); \
1537 IN_VM( \ 1634 IN_VM( \
1538 check_primitive_array_type(thr, array, ElementTag); \ 1635 check_primitive_array_type(thr, array, ElementTag); \
1539 ASSERT_OOPS_ALLOWED; \ 1636 ASSERT_OOPS_ALLOWED; \
1540 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ 1637 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 ) \ 1638 ) \
1546 UNCHECKED()->Release##Result##ArrayElements(env,array,elems,mode); \ 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); \
1547 functionExit(env); \ 1642 functionExit(env); \
1548 JNI_END 1643 JNI_END
1549 1644
1550 WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool) 1645 WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool)
1551 WRAPPER_ReleaseScalarArrayElements(T_BYTE, jbyte, Byte, byte) 1646 WRAPPER_ReleaseScalarArrayElements(T_BYTE, jbyte, Byte, byte)
1692 functionEnterCritical(thr); 1787 functionEnterCritical(thr);
1693 IN_VM( 1788 IN_VM(
1694 check_is_primitive_array(thr, array); 1789 check_is_primitive_array(thr, array);
1695 ) 1790 )
1696 void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy); 1791 void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy);
1792 if (result != NULL) {
1793 result = check_jni_wrap_copy_array(thr, array, result);
1794 }
1697 functionExit(env); 1795 functionExit(env);
1698 return result; 1796 return result;
1699 JNI_END 1797 JNI_END
1700 1798
1701 JNI_ENTRY_CHECKED(void, 1799 JNI_ENTRY_CHECKED(void,
1705 jint mode)) 1803 jint mode))
1706 functionEnterCriticalExceptionAllowed(thr); 1804 functionEnterCriticalExceptionAllowed(thr);
1707 IN_VM( 1805 IN_VM(
1708 check_is_primitive_array(thr, array); 1806 check_is_primitive_array(thr, array);
1709 ) 1807 )
1710 /* The Hotspot JNI code does not use the parameters, so just check the 1808 // Check the element array...
1711 * array parameter as a minor sanity check 1809 void* orig_result = check_wrapped_array_release(thr, "ReleasePrimitiveArrayCritical", array, carray, mode);
1712 */ 1810 UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, orig_result, mode);
1713 UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1714 functionExit(env); 1811 functionExit(env);
1715 JNI_END 1812 JNI_END
1716 1813
1717 JNI_ENTRY_CHECKED(const jchar*, 1814 JNI_ENTRY_CHECKED(const jchar*,
1718 checked_jni_GetStringCritical(JNIEnv *env, 1815 checked_jni_GetStringCritical(JNIEnv *env,