Wed, 11 Mar 2015 13:36:57 -0700
8043224: -Xcheck:jni improvements to exception checking and excessive local refs
Summary: Warning when not checking exceptions from function that require so, also when local refs expand beyond capacity.
Reviewed-by: dsimms
1.1 --- a/src/share/vm/memory/guardedMemory.hpp Mon Mar 02 13:40:40 2015 +0100 1.2 +++ b/src/share/vm/memory/guardedMemory.hpp Wed Mar 11 13:36:57 2015 -0700 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -235,7 +235,7 @@ 1.11 * @return the size of the user data. 1.12 */ 1.13 size_t get_user_size() const { 1.14 - assert(_base_addr, "Not wrapping any memory"); 1.15 + assert(_base_addr != NULL, "Not wrapping any memory"); 1.16 return get_head_guard()->get_user_size(); 1.17 } 1.18 1.19 @@ -245,7 +245,7 @@ 1.20 * @return the user data pointer. 1.21 */ 1.22 u_char* get_user_ptr() const { 1.23 - assert(_base_addr, "Not wrapping any memory"); 1.24 + assert(_base_addr != NULL, "Not wrapping any memory"); 1.25 return _base_addr + sizeof(GuardHeader); 1.26 } 1.27 1.28 @@ -281,7 +281,7 @@ 1.29 memset(get_user_ptr(), ch, get_user_size()); 1.30 } 1.31 1.32 -public: 1.33 + public: 1.34 /** 1.35 * Return the total size required for wrapping the given user size. 1.36 *
2.1 --- a/src/share/vm/prims/jniCheck.cpp Mon Mar 02 13:40:40 2015 +0100 2.2 +++ b/src/share/vm/prims/jniCheck.cpp Wed Mar 11 13:36:57 2015 -0700 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -53,6 +53,8 @@ 2.11 # include "jniTypes_ppc.hpp" 2.12 #endif 2.13 2.14 +// Complain every extra number of unplanned local refs 2.15 +#define CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD 32 2.16 2.17 // Heap objects are allowed to be directly referenced only in VM code, 2.18 // not in native code. 2.19 @@ -168,12 +170,42 @@ 2.20 * SUPPORT FUNCTIONS 2.21 */ 2.22 2.23 +/** 2.24 + * Check whether or not a programmer has actually checked for exceptions. According 2.25 + * to the JNI Specification ("jni/spec/design.html#java_exceptions"): 2.26 + * 2.27 + * There are two cases where the programmer needs to check for exceptions without 2.28 + * being able to first check an error code: 2.29 + * 2.30 + * - The JNI functions that invoke a Java method return the result of the Java method. 2.31 + * The programmer must call ExceptionOccurred() to check for possible exceptions 2.32 + * that occurred during the execution of the Java method. 2.33 + * 2.34 + * - Some of the JNI array access functions do not return an error code, but may 2.35 + * throw an ArrayIndexOutOfBoundsException or ArrayStoreException. 2.36 + * 2.37 + * In all other cases, a non-error return value guarantees that no exceptions have been thrown. 2.38 + */ 2.39 +static inline void 2.40 +check_pending_exception(JavaThread* thr) { 2.41 + if (thr->has_pending_exception()) { 2.42 + NativeReportJNIWarning(thr, "JNI call made with exception pending"); 2.43 + } 2.44 + if (thr->is_pending_jni_exception_check()) { 2.45 + IN_VM( 2.46 + tty->print_cr("WARNING in native method: JNI call made without checking exceptions when required to from %s", 2.47 + thr->get_pending_jni_exception_check()); 2.48 + thr->print_stack(); 2.49 + ) 2.50 + thr->clear_pending_jni_exception_check(); // Just complain once 2.51 + } 2.52 +} 2.53 + 2.54 + 2.55 static inline void 2.56 functionEnterCritical(JavaThread* thr) 2.57 { 2.58 - if (thr->has_pending_exception()) { 2.59 - NativeReportJNIWarning(thr, "JNI call made with exception pending"); 2.60 - } 2.61 + check_pending_exception(thr); 2.62 } 2.63 2.64 static inline void 2.65 @@ -187,9 +219,7 @@ 2.66 if (thr->in_critical()) { 2.67 tty->print_cr("%s", warn_other_function_in_critical); 2.68 } 2.69 - if (thr->has_pending_exception()) { 2.70 - NativeReportJNIWarning(thr, "JNI call made with exception pending"); 2.71 - } 2.72 + check_pending_exception(thr); 2.73 } 2.74 2.75 static inline void 2.76 @@ -201,9 +231,20 @@ 2.77 } 2.78 2.79 static inline void 2.80 -functionExit(JNIEnv *env) 2.81 +functionExit(JavaThread* thr) 2.82 { 2.83 - /* nothing to do at this time */ 2.84 + JNIHandleBlock* handles = thr->active_handles(); 2.85 + size_t planned_capacity = handles->get_planned_capacity(); 2.86 + size_t live_handles = handles->get_number_of_live_handles(); 2.87 + if (live_handles > planned_capacity) { 2.88 + IN_VM( 2.89 + tty->print_cr("WARNING: JNI local refs: %zu, exceeds capacity: %zu", 2.90 + live_handles, planned_capacity); 2.91 + thr->print_stack(); 2.92 + ) 2.93 + // Complain just the once, reset to current + warn threshold 2.94 + handles->set_planned_capacity(live_handles + CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD); 2.95 + } 2.96 } 2.97 2.98 static inline void 2.99 @@ -508,7 +549,7 @@ 2.100 jniCheck::validate_object(thr, loader); 2.101 ) 2.102 jclass result = UNCHECKED()->DefineClass(env, name, loader, buf, len); 2.103 - functionExit(env); 2.104 + functionExit(thr); 2.105 return result; 2.106 JNI_END 2.107 2.108 @@ -520,7 +561,7 @@ 2.109 jniCheck::validate_class_descriptor(thr, name); 2.110 ) 2.111 jclass result = UNCHECKED()->FindClass(env, name); 2.112 - functionExit(env); 2.113 + functionExit(thr); 2.114 return result; 2.115 JNI_END 2.116 2.117 @@ -532,7 +573,7 @@ 2.118 jniCheck::validate_object(thr, method); 2.119 ) 2.120 jmethodID result = UNCHECKED()->FromReflectedMethod(env, method); 2.121 - functionExit(env); 2.122 + functionExit(thr); 2.123 return result; 2.124 JNI_END 2.125 2.126 @@ -544,7 +585,7 @@ 2.127 jniCheck::validate_object(thr, field); 2.128 ) 2.129 jfieldID result = UNCHECKED()->FromReflectedField(env, field); 2.130 - functionExit(env); 2.131 + functionExit(thr); 2.132 return result; 2.133 JNI_END 2.134 2.135 @@ -560,7 +601,7 @@ 2.136 ) 2.137 jobject result = UNCHECKED()->ToReflectedMethod(env, cls, methodID, 2.138 isStatic); 2.139 - functionExit(env); 2.140 + functionExit(thr); 2.141 return result; 2.142 JNI_END 2.143 2.144 @@ -572,7 +613,7 @@ 2.145 jniCheck::validate_class(thr, sub, true); 2.146 ) 2.147 jclass result = UNCHECKED()->GetSuperclass(env, sub); 2.148 - functionExit(env); 2.149 + functionExit(thr); 2.150 return result; 2.151 JNI_END 2.152 2.153 @@ -586,7 +627,7 @@ 2.154 jniCheck::validate_class(thr, sup, true); 2.155 ) 2.156 jboolean result = UNCHECKED()->IsAssignableFrom(env, sub, sup); 2.157 - functionExit(env); 2.158 + functionExit(thr); 2.159 return result; 2.160 JNI_END 2.161 2.162 @@ -601,7 +642,7 @@ 2.163 ) 2.164 jobject result = UNCHECKED()->ToReflectedField(env, cls, fieldID, 2.165 isStatic); 2.166 - functionExit(env); 2.167 + functionExit(thr); 2.168 return result; 2.169 JNI_END 2.170 2.171 @@ -619,7 +660,7 @@ 2.172 } 2.173 ) 2.174 jint result = UNCHECKED()->Throw(env, obj); 2.175 - functionExit(env); 2.176 + functionExit(thr); 2.177 return result; 2.178 JNI_END 2.179 2.180 @@ -634,15 +675,16 @@ 2.181 jniCheck::validate_throwable_klass(thr, k); 2.182 ) 2.183 jint result = UNCHECKED()->ThrowNew(env, clazz, msg); 2.184 - functionExit(env); 2.185 + functionExit(thr); 2.186 return result; 2.187 JNI_END 2.188 2.189 JNI_ENTRY_CHECKED(jthrowable, 2.190 checked_jni_ExceptionOccurred(JNIEnv *env)) 2.191 + thr->clear_pending_jni_exception_check(); 2.192 functionEnterExceptionAllowed(thr); 2.193 jthrowable result = UNCHECKED()->ExceptionOccurred(env); 2.194 - functionExit(env); 2.195 + functionExit(thr); 2.196 return result; 2.197 JNI_END 2.198 2.199 @@ -650,22 +692,24 @@ 2.200 checked_jni_ExceptionDescribe(JNIEnv *env)) 2.201 functionEnterExceptionAllowed(thr); 2.202 UNCHECKED()->ExceptionDescribe(env); 2.203 - functionExit(env); 2.204 + functionExit(thr); 2.205 JNI_END 2.206 2.207 JNI_ENTRY_CHECKED(void, 2.208 checked_jni_ExceptionClear(JNIEnv *env)) 2.209 + thr->clear_pending_jni_exception_check(); 2.210 functionEnterExceptionAllowed(thr); 2.211 UNCHECKED()->ExceptionClear(env); 2.212 - functionExit(env); 2.213 + functionExit(thr); 2.214 JNI_END 2.215 2.216 JNI_ENTRY_CHECKED(void, 2.217 checked_jni_FatalError(JNIEnv *env, 2.218 const char *msg)) 2.219 + thr->clear_pending_jni_exception_check(); 2.220 functionEnter(thr); 2.221 UNCHECKED()->FatalError(env, msg); 2.222 - functionExit(env); 2.223 + functionExit(thr); 2.224 JNI_END 2.225 2.226 JNI_ENTRY_CHECKED(jint, 2.227 @@ -675,7 +719,10 @@ 2.228 if (capacity < 0) 2.229 NativeReportJNIFatalError(thr, "negative capacity"); 2.230 jint result = UNCHECKED()->PushLocalFrame(env, capacity); 2.231 - functionExit(env); 2.232 + if (result == JNI_OK) { 2.233 + thr->active_handles()->set_planned_capacity(capacity + CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD); 2.234 + } 2.235 + functionExit(thr); 2.236 return result; 2.237 JNI_END 2.238 2.239 @@ -684,7 +731,7 @@ 2.240 jobject result)) 2.241 functionEnterExceptionAllowed(thr); 2.242 jobject res = UNCHECKED()->PopLocalFrame(env, result); 2.243 - functionExit(env); 2.244 + functionExit(thr); 2.245 return res; 2.246 JNI_END 2.247 2.248 @@ -698,7 +745,7 @@ 2.249 } 2.250 ) 2.251 jobject result = UNCHECKED()->NewGlobalRef(env,lobj); 2.252 - functionExit(env); 2.253 + functionExit(thr); 2.254 return result; 2.255 JNI_END 2.256 2.257 @@ -714,7 +761,7 @@ 2.258 } 2.259 ) 2.260 UNCHECKED()->DeleteGlobalRef(env,gref); 2.261 - functionExit(env); 2.262 + functionExit(thr); 2.263 JNI_END 2.264 2.265 JNI_ENTRY_CHECKED(void, 2.266 @@ -729,7 +776,7 @@ 2.267 "Invalid local JNI handle passed to DeleteLocalRef"); 2.268 ) 2.269 UNCHECKED()->DeleteLocalRef(env, obj); 2.270 - functionExit(env); 2.271 + functionExit(thr); 2.272 JNI_END 2.273 2.274 JNI_ENTRY_CHECKED(jboolean, 2.275 @@ -750,7 +797,7 @@ 2.276 } 2.277 ) 2.278 jboolean result = UNCHECKED()->IsSameObject(env,obj1,obj2); 2.279 - functionExit(env); 2.280 + functionExit(thr); 2.281 return result; 2.282 JNI_END 2.283 2.284 @@ -764,7 +811,7 @@ 2.285 } 2.286 ) 2.287 jobject result = UNCHECKED()->NewLocalRef(env, ref); 2.288 - functionExit(env); 2.289 + functionExit(thr); 2.290 return result; 2.291 JNI_END 2.292 2.293 @@ -776,7 +823,10 @@ 2.294 NativeReportJNIFatalError(thr, "negative capacity"); 2.295 } 2.296 jint result = UNCHECKED()->EnsureLocalCapacity(env, capacity); 2.297 - functionExit(env); 2.298 + if (result == JNI_OK) { 2.299 + thr->active_handles()->set_planned_capacity(capacity + CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD); 2.300 + } 2.301 + functionExit(thr); 2.302 return result; 2.303 JNI_END 2.304 2.305 @@ -788,7 +838,7 @@ 2.306 jniCheck::validate_class(thr, clazz, false); 2.307 ) 2.308 jobject result = UNCHECKED()->AllocObject(env,clazz); 2.309 - functionExit(env); 2.310 + functionExit(thr); 2.311 return result; 2.312 JNI_END 2.313 2.314 @@ -806,7 +856,7 @@ 2.315 va_start(args, methodID); 2.316 jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args); 2.317 va_end(args); 2.318 - functionExit(env); 2.319 + functionExit(thr); 2.320 return result; 2.321 JNI_END 2.322 2.323 @@ -821,7 +871,7 @@ 2.324 jniCheck::validate_jmethod_id(thr, methodID); 2.325 ) 2.326 jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args); 2.327 - functionExit(env); 2.328 + functionExit(thr); 2.329 return result; 2.330 JNI_END 2.331 2.332 @@ -836,7 +886,7 @@ 2.333 jniCheck::validate_jmethod_id(thr, methodID); 2.334 ) 2.335 jobject result = UNCHECKED()->NewObjectA(env,clazz,methodID,args); 2.336 - functionExit(env); 2.337 + functionExit(thr); 2.338 return result; 2.339 JNI_END 2.340 2.341 @@ -848,7 +898,7 @@ 2.342 jniCheck::validate_object(thr, obj); 2.343 ) 2.344 jclass result = UNCHECKED()->GetObjectClass(env,obj); 2.345 - functionExit(env); 2.346 + functionExit(thr); 2.347 return result; 2.348 JNI_END 2.349 2.350 @@ -862,7 +912,7 @@ 2.351 jniCheck::validate_class(thr, clazz, true); 2.352 ) 2.353 jboolean result = UNCHECKED()->IsInstanceOf(env,obj,clazz); 2.354 - functionExit(env); 2.355 + functionExit(thr); 2.356 return result; 2.357 JNI_END 2.358 2.359 @@ -876,7 +926,7 @@ 2.360 jniCheck::validate_class(thr, clazz, false); 2.361 ) 2.362 jmethodID result = UNCHECKED()->GetMethodID(env,clazz,name,sig); 2.363 - functionExit(env); 2.364 + functionExit(thr); 2.365 return result; 2.366 JNI_END 2.367 2.368 @@ -895,7 +945,8 @@ 2.369 ResultType result =UNCHECKED()->Call##Result##MethodV(env, obj, methodID, \ 2.370 args); \ 2.371 va_end(args); \ 2.372 - functionExit(env); \ 2.373 + thr->set_pending_jni_exception_check("Call"#Result"Method"); \ 2.374 + functionExit(thr); \ 2.375 return result; \ 2.376 JNI_END \ 2.377 \ 2.378 @@ -910,7 +961,8 @@ 2.379 ) \ 2.380 ResultType result = UNCHECKED()->Call##Result##MethodV(env, obj, methodID,\ 2.381 args); \ 2.382 - functionExit(env); \ 2.383 + thr->set_pending_jni_exception_check("Call"#Result"MethodV"); \ 2.384 + functionExit(thr); \ 2.385 return result; \ 2.386 JNI_END \ 2.387 \ 2.388 @@ -925,7 +977,8 @@ 2.389 ) \ 2.390 ResultType result = UNCHECKED()->Call##Result##MethodA(env, obj, methodID,\ 2.391 args); \ 2.392 - functionExit(env); \ 2.393 + thr->set_pending_jni_exception_check("Call"#Result"MethodA"); \ 2.394 + functionExit(thr); \ 2.395 return result; \ 2.396 JNI_END 2.397 2.398 @@ -952,7 +1005,8 @@ 2.399 va_start(args,methodID); 2.400 UNCHECKED()->CallVoidMethodV(env,obj,methodID,args); 2.401 va_end(args); 2.402 - functionExit(env); 2.403 + thr->set_pending_jni_exception_check("CallVoidMethod"); 2.404 + functionExit(thr); 2.405 JNI_END 2.406 2.407 JNI_ENTRY_CHECKED(void, 2.408 @@ -965,7 +1019,8 @@ 2.409 jniCheck::validate_call_object(thr, obj, methodID); 2.410 ) 2.411 UNCHECKED()->CallVoidMethodV(env,obj,methodID,args); 2.412 - functionExit(env); 2.413 + thr->set_pending_jni_exception_check("CallVoidMethodV"); 2.414 + functionExit(thr); 2.415 JNI_END 2.416 2.417 JNI_ENTRY_CHECKED(void, 2.418 @@ -978,7 +1033,8 @@ 2.419 jniCheck::validate_call_object(thr, obj, methodID); 2.420 ) 2.421 UNCHECKED()->CallVoidMethodA(env,obj,methodID,args); 2.422 - functionExit(env); 2.423 + thr->set_pending_jni_exception_check("CallVoidMethodA"); 2.424 + functionExit(thr); 2.425 JNI_END 2.426 2.427 #define WRAPPER_CallNonvirtualMethod(ResultType, Result) \ 2.428 @@ -1001,7 +1057,8 @@ 2.429 methodID,\ 2.430 args); \ 2.431 va_end(args); \ 2.432 - functionExit(env); \ 2.433 + thr->set_pending_jni_exception_check("CallNonvirtual"#Result"Method"); \ 2.434 + functionExit(thr); \ 2.435 return result; \ 2.436 JNI_END \ 2.437 \ 2.438 @@ -1021,7 +1078,8 @@ 2.439 clazz, \ 2.440 methodID,\ 2.441 args); \ 2.442 - functionExit(env); \ 2.443 + thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodV"); \ 2.444 + functionExit(thr); \ 2.445 return result; \ 2.446 JNI_END \ 2.447 \ 2.448 @@ -1041,7 +1099,8 @@ 2.449 clazz, \ 2.450 methodID,\ 2.451 args); \ 2.452 - functionExit(env); \ 2.453 + thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodA"); \ 2.454 + functionExit(thr); \ 2.455 return result; \ 2.456 JNI_END 2.457 2.458 @@ -1070,7 +1129,8 @@ 2.459 va_start(args,methodID); 2.460 UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args); 2.461 va_end(args); 2.462 - functionExit(env); 2.463 + thr->set_pending_jni_exception_check("CallNonvirtualVoidMethod"); 2.464 + functionExit(thr); 2.465 JNI_END 2.466 2.467 JNI_ENTRY_CHECKED(void, 2.468 @@ -1085,7 +1145,8 @@ 2.469 jniCheck::validate_call_class(thr, clazz, methodID); 2.470 ) 2.471 UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args); 2.472 - functionExit(env); 2.473 + thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodV"); 2.474 + functionExit(thr); 2.475 JNI_END 2.476 2.477 JNI_ENTRY_CHECKED(void, 2.478 @@ -1100,7 +1161,8 @@ 2.479 jniCheck::validate_call_class(thr, clazz, methodID); 2.480 ) 2.481 UNCHECKED()->CallNonvirtualVoidMethodA(env,obj,clazz,methodID,args); 2.482 - functionExit(env); 2.483 + thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodA"); 2.484 + functionExit(thr); 2.485 JNI_END 2.486 2.487 JNI_ENTRY_CHECKED(jfieldID, 2.488 @@ -1113,7 +1175,7 @@ 2.489 jniCheck::validate_class(thr, clazz, false); 2.490 ) 2.491 jfieldID result = UNCHECKED()->GetFieldID(env,clazz,name,sig); 2.492 - functionExit(env); 2.493 + functionExit(thr); 2.494 return result; 2.495 JNI_END 2.496 2.497 @@ -1127,7 +1189,7 @@ 2.498 checkInstanceFieldID(thr, fieldID, obj, FieldType); \ 2.499 ) \ 2.500 ReturnType result = UNCHECKED()->Get##Result##Field(env,obj,fieldID); \ 2.501 - functionExit(env); \ 2.502 + functionExit(thr); \ 2.503 return result; \ 2.504 JNI_END 2.505 2.506 @@ -1152,7 +1214,7 @@ 2.507 checkInstanceFieldID(thr, fieldID, obj, FieldType); \ 2.508 ) \ 2.509 UNCHECKED()->Set##Result##Field(env,obj,fieldID,val); \ 2.510 - functionExit(env); \ 2.511 + functionExit(thr); \ 2.512 JNI_END 2.513 2.514 WRAPPER_SetField(jobject, Object, T_OBJECT) 2.515 @@ -1176,7 +1238,7 @@ 2.516 jniCheck::validate_class(thr, clazz, false); 2.517 ) 2.518 jmethodID result = UNCHECKED()->GetStaticMethodID(env,clazz,name,sig); 2.519 - functionExit(env); 2.520 + functionExit(thr); 2.521 return result; 2.522 JNI_END 2.523 2.524 @@ -1198,7 +1260,8 @@ 2.525 methodID, \ 2.526 args); \ 2.527 va_end(args); \ 2.528 - functionExit(env); \ 2.529 + thr->set_pending_jni_exception_check("CallStatic"#Result"Method"); \ 2.530 + functionExit(thr); \ 2.531 return result; \ 2.532 JNI_END \ 2.533 \ 2.534 @@ -1216,7 +1279,8 @@ 2.535 clazz, \ 2.536 methodID, \ 2.537 args); \ 2.538 - functionExit(env); \ 2.539 + thr->set_pending_jni_exception_check("CallStatic"#Result"MethodV"); \ 2.540 + functionExit(thr); \ 2.541 return result; \ 2.542 JNI_END \ 2.543 \ 2.544 @@ -1234,7 +1298,8 @@ 2.545 clazz, \ 2.546 methodID, \ 2.547 args); \ 2.548 - functionExit(env); \ 2.549 + thr->set_pending_jni_exception_check("CallStatic"#Result"MethodA"); \ 2.550 + functionExit(thr); \ 2.551 return result; \ 2.552 JNI_END 2.553 2.554 @@ -1262,7 +1327,8 @@ 2.555 va_start(args,methodID); 2.556 UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args); 2.557 va_end(args); 2.558 - functionExit(env); 2.559 + thr->set_pending_jni_exception_check("CallStaticVoidMethod"); 2.560 + functionExit(thr); 2.561 JNI_END 2.562 2.563 JNI_ENTRY_CHECKED(void, 2.564 @@ -1276,7 +1342,8 @@ 2.565 jniCheck::validate_class(thr, cls, false); 2.566 ) 2.567 UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args); 2.568 - functionExit(env); 2.569 + thr->set_pending_jni_exception_check("CallStaticVoidMethodV"); 2.570 + functionExit(thr); 2.571 JNI_END 2.572 2.573 JNI_ENTRY_CHECKED(void, 2.574 @@ -1290,7 +1357,8 @@ 2.575 jniCheck::validate_class(thr, cls, false); 2.576 ) 2.577 UNCHECKED()->CallStaticVoidMethodA(env,cls,methodID,args); 2.578 - functionExit(env); 2.579 + thr->set_pending_jni_exception_check("CallStaticVoidMethodA"); 2.580 + functionExit(thr); 2.581 JNI_END 2.582 2.583 JNI_ENTRY_CHECKED(jfieldID, 2.584 @@ -1303,7 +1371,7 @@ 2.585 jniCheck::validate_class(thr, clazz, false); 2.586 ) 2.587 jfieldID result = UNCHECKED()->GetStaticFieldID(env,clazz,name,sig); 2.588 - functionExit(env); 2.589 + functionExit(thr); 2.590 return result; 2.591 JNI_END 2.592 2.593 @@ -1320,7 +1388,7 @@ 2.594 ReturnType result = UNCHECKED()->GetStatic##Result##Field(env, \ 2.595 clazz, \ 2.596 fieldID); \ 2.597 - functionExit(env); \ 2.598 + functionExit(thr); \ 2.599 return result; \ 2.600 JNI_END 2.601 2.602 @@ -1346,7 +1414,7 @@ 2.603 checkStaticFieldID(thr, fieldID, clazz, FieldType); \ 2.604 ) \ 2.605 UNCHECKED()->SetStatic##Result##Field(env,clazz,fieldID,value); \ 2.606 - functionExit(env); \ 2.607 + functionExit(thr); \ 2.608 JNI_END 2.609 2.610 WRAPPER_SetStaticField(jobject, Object, T_OBJECT) 2.611 @@ -1366,7 +1434,7 @@ 2.612 jsize len)) 2.613 functionEnter(thr); 2.614 jstring result = UNCHECKED()->NewString(env,unicode,len); 2.615 - functionExit(env); 2.616 + functionExit(thr); 2.617 return result; 2.618 JNI_END 2.619 2.620 @@ -1378,7 +1446,7 @@ 2.621 checkString(thr, str); 2.622 ) 2.623 jsize result = UNCHECKED()->GetStringLength(env,str); 2.624 - functionExit(env); 2.625 + functionExit(thr); 2.626 return result; 2.627 JNI_END 2.628 2.629 @@ -1407,7 +1475,7 @@ 2.630 // Note that the dtrace arguments for the allocated memory will not match up with this solution. 2.631 FreeHeap((char*)result); 2.632 } 2.633 - functionExit(env); 2.634 + functionExit(thr); 2.635 return new_result; 2.636 JNI_END 2.637 2.638 @@ -1442,7 +1510,7 @@ 2.639 UNCHECKED()->ReleaseStringChars(env, str, 2.640 (const jchar*) guarded.release_for_freeing()); 2.641 } 2.642 - functionExit(env); 2.643 + functionExit(thr); 2.644 JNI_END 2.645 2.646 JNI_ENTRY_CHECKED(jstring, 2.647 @@ -1450,7 +1518,7 @@ 2.648 const char *utf)) 2.649 functionEnter(thr); 2.650 jstring result = UNCHECKED()->NewStringUTF(env,utf); 2.651 - functionExit(env); 2.652 + functionExit(thr); 2.653 return result; 2.654 JNI_END 2.655 2.656 @@ -1462,7 +1530,7 @@ 2.657 checkString(thr, str); 2.658 ) 2.659 jsize result = UNCHECKED()->GetStringUTFLength(env,str); 2.660 - functionExit(env); 2.661 + functionExit(thr); 2.662 return result; 2.663 JNI_END 2.664 2.665 @@ -1490,7 +1558,7 @@ 2.666 // Note that the dtrace arguments for the allocated memory will not match up with this solution. 2.667 FreeHeap((char*)result, mtInternal); 2.668 } 2.669 - functionExit(env); 2.670 + functionExit(thr); 2.671 return new_result; 2.672 JNI_END 2.673 2.674 @@ -1525,7 +1593,7 @@ 2.675 UNCHECKED()->ReleaseStringUTFChars(env, str, 2.676 (const char*) guarded.release_for_freeing()); 2.677 } 2.678 - functionExit(env); 2.679 + functionExit(thr); 2.680 JNI_END 2.681 2.682 JNI_ENTRY_CHECKED(jsize, 2.683 @@ -1536,7 +1604,7 @@ 2.684 check_is_array(thr, array); 2.685 ) 2.686 jsize result = UNCHECKED()->GetArrayLength(env,array); 2.687 - functionExit(env); 2.688 + functionExit(thr); 2.689 return result; 2.690 JNI_END 2.691 2.692 @@ -1547,7 +1615,7 @@ 2.693 jobject init)) 2.694 functionEnter(thr); 2.695 jobjectArray result = UNCHECKED()->NewObjectArray(env,len,clazz,init); 2.696 - functionExit(env); 2.697 + functionExit(thr); 2.698 return result; 2.699 JNI_END 2.700 2.701 @@ -1560,7 +1628,8 @@ 2.702 check_is_obj_array(thr, array); 2.703 ) 2.704 jobject result = UNCHECKED()->GetObjectArrayElement(env,array,index); 2.705 - functionExit(env); 2.706 + thr->set_pending_jni_exception_check("GetObjectArrayElement"); 2.707 + functionExit(thr); 2.708 return result; 2.709 JNI_END 2.710 2.711 @@ -1574,7 +1643,8 @@ 2.712 check_is_obj_array(thr, array); 2.713 ) 2.714 UNCHECKED()->SetObjectArrayElement(env,array,index,val); 2.715 - functionExit(env); 2.716 + thr->set_pending_jni_exception_check("SetObjectArrayElement"); 2.717 + functionExit(thr); 2.718 JNI_END 2.719 2.720 #define WRAPPER_NewScalarArray(Return, Result) \ 2.721 @@ -1583,7 +1653,7 @@ 2.722 jsize len)) \ 2.723 functionEnter(thr); \ 2.724 Return result = UNCHECKED()->New##Result##Array(env,len); \ 2.725 - functionExit(env); \ 2.726 + functionExit(thr); \ 2.727 return (Return) result; \ 2.728 JNI_END 2.729 2.730 @@ -1611,7 +1681,7 @@ 2.731 if (result != NULL) { \ 2.732 result = (ElementType *) check_jni_wrap_copy_array(thr, array, result); \ 2.733 } \ 2.734 - functionExit(env); \ 2.735 + functionExit(thr); \ 2.736 return result; \ 2.737 JNI_END 2.738 2.739 @@ -1639,7 +1709,7 @@ 2.740 ElementType* orig_result = (ElementType *) check_wrapped_array_release( \ 2.741 thr, "checked_jni_Release"#Result"ArrayElements", array, elems, mode); \ 2.742 UNCHECKED()->Release##Result##ArrayElements(env, array, orig_result, mode); \ 2.743 - functionExit(env); \ 2.744 + functionExit(thr); \ 2.745 JNI_END 2.746 2.747 WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool) 2.748 @@ -1663,7 +1733,8 @@ 2.749 check_primitive_array_type(thr, array, ElementTag); \ 2.750 ) \ 2.751 UNCHECKED()->Get##Result##ArrayRegion(env,array,start,len,buf); \ 2.752 - functionExit(env); \ 2.753 + thr->set_pending_jni_exception_check("Get"#Result"ArrayRegion"); \ 2.754 + functionExit(thr); \ 2.755 JNI_END 2.756 2.757 WRAPPER_GetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean) 2.758 @@ -1687,7 +1758,8 @@ 2.759 check_primitive_array_type(thr, array, ElementTag); \ 2.760 ) \ 2.761 UNCHECKED()->Set##Result##ArrayRegion(env,array,start,len,buf); \ 2.762 - functionExit(env); \ 2.763 + thr->set_pending_jni_exception_check("Set"#Result"ArrayRegion"); \ 2.764 + functionExit(thr); \ 2.765 JNI_END 2.766 2.767 WRAPPER_SetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean) 2.768 @@ -1706,7 +1778,7 @@ 2.769 jint nMethods)) 2.770 functionEnter(thr); 2.771 jint result = UNCHECKED()->RegisterNatives(env,clazz,methods,nMethods); 2.772 - functionExit(env); 2.773 + functionExit(thr); 2.774 return result; 2.775 JNI_END 2.776 2.777 @@ -1715,7 +1787,7 @@ 2.778 jclass clazz)) 2.779 functionEnter(thr); 2.780 jint result = UNCHECKED()->UnregisterNatives(env,clazz); 2.781 - functionExit(env); 2.782 + functionExit(thr); 2.783 return result; 2.784 JNI_END 2.785 2.786 @@ -1727,7 +1799,7 @@ 2.787 jniCheck::validate_object(thr, obj); 2.788 ) 2.789 jint result = UNCHECKED()->MonitorEnter(env,obj); 2.790 - functionExit(env); 2.791 + functionExit(thr); 2.792 return result; 2.793 JNI_END 2.794 2.795 @@ -1739,7 +1811,7 @@ 2.796 jniCheck::validate_object(thr, obj); 2.797 ) 2.798 jint result = UNCHECKED()->MonitorExit(env,obj); 2.799 - functionExit(env); 2.800 + functionExit(thr); 2.801 return result; 2.802 JNI_END 2.803 2.804 @@ -1748,7 +1820,7 @@ 2.805 JavaVM **vm)) 2.806 functionEnter(thr); 2.807 jint result = UNCHECKED()->GetJavaVM(env,vm); 2.808 - functionExit(env); 2.809 + functionExit(thr); 2.810 return result; 2.811 JNI_END 2.812 2.813 @@ -1763,7 +1835,8 @@ 2.814 checkString(thr, str); 2.815 ) 2.816 UNCHECKED()->GetStringRegion(env, str, start, len, buf); 2.817 - functionExit(env); 2.818 + thr->set_pending_jni_exception_check("GetStringRegion"); 2.819 + functionExit(thr); 2.820 JNI_END 2.821 2.822 JNI_ENTRY_CHECKED(void, 2.823 @@ -1777,7 +1850,8 @@ 2.824 checkString(thr, str); 2.825 ) 2.826 UNCHECKED()->GetStringUTFRegion(env, str, start, len, buf); 2.827 - functionExit(env); 2.828 + thr->set_pending_jni_exception_check("GetStringUTFRegion"); 2.829 + functionExit(thr); 2.830 JNI_END 2.831 2.832 JNI_ENTRY_CHECKED(void *, 2.833 @@ -1792,7 +1866,7 @@ 2.834 if (result != NULL) { 2.835 result = check_jni_wrap_copy_array(thr, array, result); 2.836 } 2.837 - functionExit(env); 2.838 + functionExit(thr); 2.839 return result; 2.840 JNI_END 2.841 2.842 @@ -1808,7 +1882,7 @@ 2.843 // Check the element array... 2.844 void* orig_result = check_wrapped_array_release(thr, "ReleasePrimitiveArrayCritical", array, carray, mode); 2.845 UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, orig_result, mode); 2.846 - functionExit(env); 2.847 + functionExit(thr); 2.848 JNI_END 2.849 2.850 JNI_ENTRY_CHECKED(const jchar*, 2.851 @@ -1820,7 +1894,7 @@ 2.852 checkString(thr, string); 2.853 ) 2.854 const jchar *result = UNCHECKED()->GetStringCritical(env, string, isCopy); 2.855 - functionExit(env); 2.856 + functionExit(thr); 2.857 return result; 2.858 JNI_END 2.859 2.860 @@ -1836,7 +1910,7 @@ 2.861 * string parameter as a minor sanity check 2.862 */ 2.863 UNCHECKED()->ReleaseStringCritical(env, str, chars); 2.864 - functionExit(env); 2.865 + functionExit(thr); 2.866 JNI_END 2.867 2.868 JNI_ENTRY_CHECKED(jweak, 2.869 @@ -1849,7 +1923,7 @@ 2.870 } 2.871 ) 2.872 jweak result = UNCHECKED()->NewWeakGlobalRef(env, obj); 2.873 - functionExit(env); 2.874 + functionExit(thr); 2.875 return result; 2.876 JNI_END 2.877 2.878 @@ -1858,14 +1932,15 @@ 2.879 jweak ref)) 2.880 functionEnterExceptionAllowed(thr); 2.881 UNCHECKED()->DeleteWeakGlobalRef(env, ref); 2.882 - functionExit(env); 2.883 + functionExit(thr); 2.884 JNI_END 2.885 2.886 JNI_ENTRY_CHECKED(jboolean, 2.887 checked_jni_ExceptionCheck(JNIEnv *env)) 2.888 + thr->clear_pending_jni_exception_check(); 2.889 functionEnterExceptionAllowed(thr); 2.890 jboolean result = UNCHECKED()->ExceptionCheck(env); 2.891 - functionExit(env); 2.892 + functionExit(thr); 2.893 return result; 2.894 JNI_END 2.895 2.896 @@ -1875,7 +1950,7 @@ 2.897 jlong capacity)) 2.898 functionEnter(thr); 2.899 jobject result = UNCHECKED()->NewDirectByteBuffer(env, address, capacity); 2.900 - functionExit(env); 2.901 + functionExit(thr); 2.902 return result; 2.903 JNI_END 2.904 2.905 @@ -1884,7 +1959,7 @@ 2.906 jobject buf)) 2.907 functionEnter(thr); 2.908 void* result = UNCHECKED()->GetDirectBufferAddress(env, buf); 2.909 - functionExit(env); 2.910 + functionExit(thr); 2.911 return result; 2.912 JNI_END 2.913 2.914 @@ -1893,7 +1968,7 @@ 2.915 jobject buf)) 2.916 functionEnter(thr); 2.917 jlong result = UNCHECKED()->GetDirectBufferCapacity(env, buf); 2.918 - functionExit(env); 2.919 + functionExit(thr); 2.920 return result; 2.921 JNI_END 2.922 2.923 @@ -1906,7 +1981,7 @@ 2.924 jniCheck::validate_object(thr, obj); 2.925 ) 2.926 jobjectRefType result = UNCHECKED()->GetObjectRefType(env, obj); 2.927 - functionExit(env); 2.928 + functionExit(thr); 2.929 return result; 2.930 JNI_END 2.931 2.932 @@ -1915,7 +1990,7 @@ 2.933 checked_jni_GetVersion(JNIEnv *env)) 2.934 functionEnter(thr); 2.935 jint result = UNCHECKED()->GetVersion(env); 2.936 - functionExit(env); 2.937 + functionExit(thr); 2.938 return result; 2.939 JNI_END 2.940
3.1 --- a/src/share/vm/runtime/jniHandles.cpp Mon Mar 02 13:40:40 2015 +0100 3.2 +++ b/src/share/vm/runtime/jniHandles.cpp Wed Mar 11 13:36:57 2015 -0700 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -296,6 +296,7 @@ 3.11 block->_top = 0; 3.12 block->_next = NULL; 3.13 block->_pop_frame_link = NULL; 3.14 + block->_planned_capacity = block_size_in_oops; 3.15 // _last, _free_list & _allocate_before_rebuild initialized in allocate_handle 3.16 debug_only(block->_last = NULL); 3.17 debug_only(block->_free_list = NULL); 3.18 @@ -529,6 +530,12 @@ 3.19 return result; 3.20 } 3.21 3.22 +const size_t JNIHandleBlock::get_number_of_live_handles() { 3.23 + CountHandleClosure counter; 3.24 + oops_do(&counter); 3.25 + return counter.count(); 3.26 +} 3.27 + 3.28 // This method is not thread-safe, i.e., must be called whule holding a lock on the 3.29 // structure. 3.30 long JNIHandleBlock::memory_usage() const {
4.1 --- a/src/share/vm/runtime/jniHandles.hpp Mon Mar 02 13:40:40 2015 +0100 4.2 +++ b/src/share/vm/runtime/jniHandles.hpp Wed Mar 11 13:36:57 2015 -0700 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. 4.6 + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 4.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 * 4.9 * This code is free software; you can redistribute it and/or modify it 4.10 @@ -112,6 +112,9 @@ 4.11 oop* _free_list; // Handle free list 4.12 int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list 4.13 4.14 + // Check JNI, "planned capacity" for current frame (or push/ensure) 4.15 + size_t _planned_capacity; 4.16 + 4.17 #ifndef PRODUCT 4.18 JNIHandleBlock* _block_list_link; // Link for list below 4.19 static JNIHandleBlock* _block_list; // List of all allocated blocks (for debugging only) 4.20 @@ -152,6 +155,11 @@ 4.21 // Traversal of weak handles. Unreachable oops are cleared. 4.22 void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f); 4.23 4.24 + // Checked JNI support 4.25 + void set_planned_capacity(size_t planned_capacity) { _planned_capacity = planned_capacity; } 4.26 + const size_t get_planned_capacity() { return _planned_capacity; } 4.27 + const size_t get_number_of_live_handles(); 4.28 + 4.29 // Debugging 4.30 bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle 4.31 bool contains(jobject handle) const; // Does this block contain handle
5.1 --- a/src/share/vm/runtime/thread.cpp Mon Mar 02 13:40:40 2015 +0100 5.2 +++ b/src/share/vm/runtime/thread.cpp Wed Mar 11 13:36:57 2015 -0700 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 5.6 + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -1465,6 +1465,7 @@ 5.11 _thread_stat = new ThreadStatistics(); 5.12 _blocked_on_compilation = false; 5.13 _jni_active_critical = 0; 5.14 + _pending_jni_exception_check_fn = NULL; 5.15 _do_not_unlock_if_synchronized = false; 5.16 _cached_monitor_info = NULL; 5.17 _parker = Parker::Allocate(this) ;
6.1 --- a/src/share/vm/runtime/thread.hpp Mon Mar 02 13:40:40 2015 +0100 6.2 +++ b/src/share/vm/runtime/thread.hpp Wed Mar 11 13:36:57 2015 -0700 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 6.6 + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.8 * 6.9 * This code is free software; you can redistribute it and/or modify it 6.10 @@ -926,6 +926,9 @@ 6.11 // support for JNI critical regions 6.12 jint _jni_active_critical; // count of entries into JNI critical region 6.13 6.14 + // Checked JNI: function name requires exception check 6.15 + char* _pending_jni_exception_check_fn; 6.16 + 6.17 // For deadlock detection. 6.18 int _depth_first_number; 6.19 6.20 @@ -1408,6 +1411,12 @@ 6.21 assert(_jni_active_critical >= 0, 6.22 "JNI critical nesting problem?"); } 6.23 6.24 + // Checked JNI, is the programmer required to check for exceptions, specify which function name 6.25 + bool is_pending_jni_exception_check() const { return _pending_jni_exception_check_fn != NULL; } 6.26 + void clear_pending_jni_exception_check() { _pending_jni_exception_check_fn = NULL; } 6.27 + const char* get_pending_jni_exception_check() const { return _pending_jni_exception_check_fn; } 6.28 + void set_pending_jni_exception_check(const char* fn_name) { _pending_jni_exception_check_fn = (char*) fn_name; } 6.29 + 6.30 // For deadlock detection 6.31 int depth_first_number() { return _depth_first_number; } 6.32 void set_depth_first_number(int dfn) { _depth_first_number = dfn; }