8043224: -Xcheck:jni improvements to exception checking and excessive local refs

Wed, 11 Mar 2015 13:36:57 -0700

author
poonam
date
Wed, 11 Mar 2015 13:36:57 -0700
changeset 7627
d68158e12cea
parent 7626
364f6c28effb
child 7628
d51ef6da82b4
child 7632
ffae627760ca
child 7662
6d817035633c

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

src/share/vm/memory/guardedMemory.hpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jniCheck.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/jniHandles.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/jniHandles.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.hpp file | annotate | diff | comparison | revisions
     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; }

mercurial