| /* |
| * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| */ |
| |
| #include "precompiled.hpp" |
| #include "classfile/javaClasses.inline.hpp" |
| #include "classfile/systemDictionary.hpp" |
| #include "classfile/vmSymbols.hpp" |
| #include "memory/guardedMemory.hpp" |
| #include "oops/instanceKlass.hpp" |
| #include "oops/oop.inline.hpp" |
| #include "oops/symbol.hpp" |
| #include "prims/jni.h" |
| #include "prims/jniCheck.hpp" |
| #include "prims/jvm.h" |
| #include "prims/jvm_misc.hpp" |
| #include "runtime/fieldDescriptor.hpp" |
| #include "runtime/handles.hpp" |
| #include "runtime/interfaceSupport.hpp" |
| #include "runtime/jfieldIDWorkaround.hpp" |
| #include "runtime/thread.inline.hpp" |
| |
| // Complain every extra number of unplanned local refs |
| #define CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD 32 |
| |
| // Heap objects are allowed to be directly referenced only in VM code, |
| // not in native code. |
| |
| #define ASSERT_OOPS_ALLOWED \ |
| assert(JavaThread::current()->thread_state() == _thread_in_vm, \ |
| "jniCheck examining oops in bad state.") |
| |
| |
| // Execute the given block of source code with the thread in VM state. |
| // To do this, transition from the NATIVE state to the VM state, execute |
| // the code, and transtition back. The ThreadInVMfromNative constructor |
| // performs the transition to VM state, its destructor restores the |
| // NATIVE state. |
| |
| #define IN_VM(source_code) { \ |
| { \ |
| ThreadInVMfromNative __tiv(thr); \ |
| source_code \ |
| } \ |
| } |
| |
| |
| /* |
| * DECLARATIONS |
| */ |
| |
| static struct JNINativeInterface_ * unchecked_jni_NativeInterface; |
| |
| |
| /* |
| * MACRO DEFINITIONS |
| */ |
| |
| // All JNI checked functions here use JNI_ENTRY_CHECKED() instead of the |
| // QUICK_ENTRY or LEAF variants found in jni.cpp. This allows handles |
| // to be created if a fatal error should occur. |
| |
| // Check for thread not attached to VM; need to catch this before |
| // assertions in the wrapper routines might fire |
| |
| // Check for env being the one value appropriate for this thread. |
| |
| #define JNI_ENTRY_CHECKED(result_type, header) \ |
| extern "C" { \ |
| result_type JNICALL header { \ |
| JavaThread* thr = (JavaThread*) Thread::current_or_null(); \ |
| if (thr == NULL || !thr->is_Java_thread()) { \ |
| tty->print_cr("%s", fatal_using_jnienv_in_nonjava); \ |
| os::abort(true); \ |
| } \ |
| JNIEnv* xenv = thr->jni_environment(); \ |
| if (env != xenv) { \ |
| NativeReportJNIFatalError(thr, warn_wrong_jnienv); \ |
| } \ |
| VM_ENTRY_BASE(result_type, header, thr) |
| |
| |
| #define UNCHECKED() (unchecked_jni_NativeInterface) |
| |
| static const char * warn_wrong_jnienv = "Using JNIEnv in the wrong thread"; |
| static const char * warn_bad_class_descriptor1 = "JNI FindClass received a bad class descriptor \""; |
| static const char * warn_bad_class_descriptor2 = "\". A correct class descriptor " \ |
| "has no leading \"L\" or trailing \";\". Incorrect descriptors will not be accepted in future releases."; |
| static const char * fatal_using_jnienv_in_nonjava = "FATAL ERROR in native method: Using JNIEnv in non-Java thread"; |
| static const char * warn_other_function_in_critical = "Warning: Calling other JNI functions in the scope of " \ |
| "Get/ReleasePrimitiveArrayCritical or Get/ReleaseStringCritical"; |
| static const char * fatal_bad_ref_to_jni = "Bad global or local ref passed to JNI"; |
| static const char * fatal_received_null_class = "JNI received a null class"; |
| static const char * fatal_class_not_a_class = "JNI received a class argument that is not a class"; |
| static const char * fatal_class_not_a_throwable_class = "JNI Throw or ThrowNew received a class argument that is not a Throwable or Throwable subclass"; |
| static const char * fatal_wrong_class_or_method = "Wrong object class or methodID passed to JNI call"; |
| static const char * fatal_non_weak_method = "non-weak methodID passed to JNI call"; |
| static const char * fatal_unknown_array_object = "Unknown array object passed to JNI array operations"; |
| static const char * fatal_object_array_expected = "Object array expected but not received for JNI array operation"; |
| static const char * fatal_prim_type_array_expected = "Primitive type array expected but not received for JNI array operation"; |
| static const char * fatal_non_array = "Non-array passed to JNI array operations"; |
| static const char * fatal_element_type_mismatch = "Array element type mismatch in JNI"; |
| static const char * fatal_should_be_static = "Non-static field ID passed to JNI"; |
| static const char * fatal_wrong_static_field = "Wrong static field ID passed to JNI"; |
| static const char * fatal_static_field_not_found = "Static field not found in JNI get/set field operations"; |
| static const char * fatal_static_field_mismatch = "Field type (static) mismatch in JNI get/set field operations"; |
| static const char * fatal_should_be_nonstatic = "Static field ID passed to JNI"; |
| static const char * fatal_null_object = "Null object passed to JNI"; |
| static const char * fatal_wrong_field = "Wrong field ID passed to JNI"; |
| static const char * fatal_instance_field_not_found = "Instance field not found in JNI get/set field operations"; |
| static const char * fatal_instance_field_mismatch = "Field type (instance) mismatch in JNI get/set field operations"; |
| static const char * fatal_non_string = "JNI string operation received a non-string"; |
| |
| |
| // When in VM state: |
| static void ReportJNIWarning(JavaThread* thr, const char *msg) { |
| tty->print_cr("WARNING in native method: %s", msg); |
| thr->print_stack(); |
| } |
| |
| // When in NATIVE state: |
| static void NativeReportJNIFatalError(JavaThread* thr, const char *msg) { |
| IN_VM( |
| ReportJNIFatalError(thr, msg); |
| ) |
| } |
| |
| static void NativeReportJNIWarning(JavaThread* thr, const char *msg) { |
| IN_VM( |
| ReportJNIWarning(thr, msg); |
| ) |
| } |
| |
| |
| |
| |
| /* |
| * SUPPORT FUNCTIONS |
| */ |
| |
| /** |
| * Check whether or not a programmer has actually checked for exceptions. According |
| * to the JNI Specification ("jni/spec/design.html#java_exceptions"): |
| * |
| * There are two cases where the programmer needs to check for exceptions without |
| * being able to first check an error code: |
| * |
| * - The JNI functions that invoke a Java method return the result of the Java method. |
| * The programmer must call ExceptionOccurred() to check for possible exceptions |
| * that occurred during the execution of the Java method. |
| * |
| * - Some of the JNI array access functions do not return an error code, but may |
| * throw an ArrayIndexOutOfBoundsException or ArrayStoreException. |
| * |
| * In all other cases, a non-error return value guarantees that no exceptions have been thrown. |
| * |
| * Programmers often defend against ArrayIndexOutOfBoundsException, so warning |
| * for these functions would be pedantic. |
| */ |
| static inline void |
| check_pending_exception(JavaThread* thr) { |
| if (thr->has_pending_exception()) { |
| NativeReportJNIWarning(thr, "JNI call made with exception pending"); |
| } |
| if (thr->is_pending_jni_exception_check()) { |
| IN_VM( |
| tty->print_cr("WARNING in native method: JNI call made without checking exceptions when required to from %s", |
| thr->get_pending_jni_exception_check()); |
| thr->print_stack(); |
| ) |
| thr->clear_pending_jni_exception_check(); // Just complain once |
| } |
| } |
| |
| /** |
| * Add to the planned number of handles. I.e. plus current live & warning threshold |
| */ |
| static inline void |
| add_planned_handle_capacity(JNIHandleBlock* handles, size_t capacity) { |
| handles->set_planned_capacity(capacity + |
| handles->get_number_of_live_handles() + |
| CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD); |
| } |
| |
| |
| static inline void |
| functionEnterCritical(JavaThread* thr) |
| { |
| check_pending_exception(thr); |
| } |
| |
| static inline void |
| functionEnterCriticalExceptionAllowed(JavaThread* thr) |
| { |
| } |
| |
| static inline void |
| functionEnter(JavaThread* thr) |
| { |
| if (thr->in_critical()) { |
| tty->print_cr("%s", warn_other_function_in_critical); |
| } |
| check_pending_exception(thr); |
| } |
| |
| static inline void |
| functionEnterExceptionAllowed(JavaThread* thr) |
| { |
| if (thr->in_critical()) { |
| tty->print_cr("%s", warn_other_function_in_critical); |
| } |
| } |
| |
| static inline void |
| functionExit(JavaThread* thr) |
| { |
| JNIHandleBlock* handles = thr->active_handles(); |
| size_t planned_capacity = handles->get_planned_capacity(); |
| size_t live_handles = handles->get_number_of_live_handles(); |
| if (live_handles > planned_capacity) { |
| IN_VM( |
| tty->print_cr("WARNING: JNI local refs: " SIZE_FORMAT ", exceeds capacity: " SIZE_FORMAT, |
| live_handles, planned_capacity); |
| thr->print_stack(); |
| ) |
| // Complain just the once, reset to current + warn threshold |
| add_planned_handle_capacity(handles, 0); |
| } |
| } |
| |
| static inline void |
| checkStaticFieldID(JavaThread* thr, jfieldID fid, jclass cls, int ftype) |
| { |
| fieldDescriptor fd; |
| |
| /* make sure it is a static field */ |
| if (!jfieldIDWorkaround::is_static_jfieldID(fid)) |
| ReportJNIFatalError(thr, fatal_should_be_static); |
| |
| /* validate the class being passed */ |
| ASSERT_OOPS_ALLOWED; |
| Klass* k_oop = jniCheck::validate_class(thr, cls, false); |
| |
| /* check for proper subclass hierarchy */ |
| JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fid); |
| Klass* f_oop = id->holder(); |
| if (!InstanceKlass::cast(k_oop)->is_subtype_of(f_oop)) |
| ReportJNIFatalError(thr, fatal_wrong_static_field); |
| |
| /* check for proper field type */ |
| if (!id->find_local_field(&fd)) |
| ReportJNIFatalError(thr, fatal_static_field_not_found); |
| if ((fd.field_type() != ftype) && |
| !(fd.field_type() == T_ARRAY && ftype == T_OBJECT)) { |
| ReportJNIFatalError(thr, fatal_static_field_mismatch); |
| } |
| } |
| |
| static inline void |
| checkInstanceFieldID(JavaThread* thr, jfieldID fid, jobject obj, int ftype) |
| { |
| fieldDescriptor fd; |
| |
| /* make sure it is an instance field */ |
| if (jfieldIDWorkaround::is_static_jfieldID(fid)) |
| ReportJNIFatalError(thr, fatal_should_be_nonstatic); |
| |
| /* validate the object being passed and then get its class */ |
| ASSERT_OOPS_ALLOWED; |
| oop oopObj = jniCheck::validate_object(thr, obj); |
| if (!oopObj) { |
| ReportJNIFatalError(thr, fatal_null_object); |
| } |
| Klass* k_oop = oopObj->klass(); |
| |
| if (!jfieldIDWorkaround::is_valid_jfieldID(k_oop, fid)) { |
| ReportJNIFatalError(thr, fatal_wrong_field); |
| } |
| |
| /* make sure the field exists */ |
| int offset = jfieldIDWorkaround::from_instance_jfieldID(k_oop, fid); |
| if (!InstanceKlass::cast(k_oop)->contains_field_offset(offset)) |
| ReportJNIFatalError(thr, fatal_wrong_field); |
| |
| /* check for proper field type */ |
| if (!InstanceKlass::cast(k_oop)->find_field_from_offset(offset, |
| false, &fd)) |
| ReportJNIFatalError(thr, fatal_instance_field_not_found); |
| |
| if ((fd.field_type() != ftype) && |
| !(fd.field_type() == T_ARRAY && ftype == T_OBJECT)) { |
| ReportJNIFatalError(thr, fatal_instance_field_mismatch); |
| } |
| } |
| |
| static inline void |
| checkString(JavaThread* thr, jstring js) |
| { |
| ASSERT_OOPS_ALLOWED; |
| oop s = jniCheck::validate_object(thr, js); |
| if (!s || !java_lang_String::is_instance(s)) |
| ReportJNIFatalError(thr, fatal_non_string); |
| } |
| |
| static inline arrayOop |
| check_is_array(JavaThread* thr, jarray jArray) |
| { |
| ASSERT_OOPS_ALLOWED; |
| arrayOop aOop; |
| |
| aOop = (arrayOop)jniCheck::validate_object(thr, jArray); |
| if (aOop == NULL || !aOop->is_array()) { |
| ReportJNIFatalError(thr, fatal_non_array); |
| } |
| return aOop; |
| } |
| |
| static inline arrayOop |
| check_is_primitive_array(JavaThread* thr, jarray jArray) { |
| arrayOop aOop = check_is_array(thr, jArray); |
| |
| if (!aOop->is_typeArray()) { |
| ReportJNIFatalError(thr, fatal_prim_type_array_expected); |
| } |
| return aOop; |
| } |
| |
| static inline void |
| check_primitive_array_type(JavaThread* thr, jarray jArray, BasicType elementType) |
| { |
| BasicType array_type; |
| arrayOop aOop; |
| |
| aOop = check_is_primitive_array(thr, jArray); |
| array_type = TypeArrayKlass::cast(aOop->klass())->element_type(); |
| if (array_type != elementType) { |
| ReportJNIFatalError(thr, fatal_element_type_mismatch); |
| } |
| } |
| |
| static inline void |
| check_is_obj_array(JavaThread* thr, jarray jArray) { |
| arrayOop aOop = check_is_array(thr, jArray); |
| if (!aOop->is_objArray()) { |
| ReportJNIFatalError(thr, fatal_object_array_expected); |
| } |
| } |
| |
| /* |
| * Copy and wrap array elements for bounds checking. |
| * Remember the original elements (GuardedMemory::get_tag()) |
| */ |
| static void* check_jni_wrap_copy_array(JavaThread* thr, jarray array, |
| void* orig_elements) { |
| void* result; |
| IN_VM( |
| oop a = JNIHandles::resolve_non_null(array); |
| size_t len = arrayOop(a)->length() << |
| TypeArrayKlass::cast(a->klass())->log2_element_size(); |
| result = GuardedMemory::wrap_copy(orig_elements, len, orig_elements); |
| ) |
| return result; |
| } |
| |
| static void* check_wrapped_array(JavaThread* thr, const char* fn_name, |
| void* obj, void* carray, size_t* rsz) { |
| if (carray == NULL) { |
| tty->print_cr("%s: elements vector NULL" PTR_FORMAT, fn_name, p2i(obj)); |
| NativeReportJNIFatalError(thr, "Elements vector NULL"); |
| } |
| GuardedMemory guarded(carray); |
| void* orig_result = guarded.get_tag(); |
| if (!guarded.verify_guards()) { |
| tty->print_cr("ReleasePrimitiveArrayCritical: release array failed bounds " |
| "check, incorrect pointer returned ? array: " PTR_FORMAT " carray: " |
| PTR_FORMAT, p2i(obj), p2i(carray)); |
| guarded.print_on(tty); |
| NativeReportJNIFatalError(thr, "ReleasePrimitiveArrayCritical: " |
| "failed bounds check"); |
| } |
| if (orig_result == NULL) { |
| tty->print_cr("ReleasePrimitiveArrayCritical: unrecognized elements. array: " |
| PTR_FORMAT " carray: " PTR_FORMAT, p2i(obj), p2i(carray)); |
| guarded.print_on(tty); |
| NativeReportJNIFatalError(thr, "ReleasePrimitiveArrayCritical: " |
| "unrecognized elements"); |
| } |
| if (rsz != NULL) { |
| *rsz = guarded.get_user_size(); |
| } |
| return orig_result; |
| } |
| |
| static void* check_wrapped_array_release(JavaThread* thr, const char* fn_name, |
| void* obj, void* carray, jint mode) { |
| size_t sz; |
| void* orig_result = check_wrapped_array(thr, fn_name, obj, carray, &sz); |
| switch (mode) { |
| case 0: |
| memcpy(orig_result, carray, sz); |
| GuardedMemory::free_copy(carray); |
| break; |
| case JNI_COMMIT: |
| memcpy(orig_result, carray, sz); |
| break; |
| case JNI_ABORT: |
| GuardedMemory::free_copy(carray); |
| break; |
| default: |
| tty->print_cr("%s: Unrecognized mode %i releasing array " |
| PTR_FORMAT " elements " PTR_FORMAT, fn_name, mode, p2i(obj), p2i(carray)); |
| NativeReportJNIFatalError(thr, "Unrecognized array release mode"); |
| } |
| return orig_result; |
| } |
| |
| oop jniCheck::validate_handle(JavaThread* thr, jobject obj) { |
| if (JNIHandles::is_frame_handle(thr, obj) || |
| JNIHandles::is_local_handle(thr, obj) || |
| JNIHandles::is_global_handle(obj) || |
| JNIHandles::is_weak_global_handle(obj)) { |
| ASSERT_OOPS_ALLOWED; |
| return JNIHandles::resolve_external_guard(obj); |
| } |
| ReportJNIFatalError(thr, fatal_bad_ref_to_jni); |
| return NULL; |
| } |
| |
| |
| Method* jniCheck::validate_jmethod_id(JavaThread* thr, jmethodID method_id) { |
| ASSERT_OOPS_ALLOWED; |
| // do the fast jmethodID check first |
| Method* moop = Method::checked_resolve_jmethod_id(method_id); |
| if (moop == NULL) { |
| ReportJNIFatalError(thr, fatal_wrong_class_or_method); |
| } |
| // jmethodIDs are supposed to be weak handles in the class loader data, |
| // but that can be expensive so check it last |
| else if (!Method::is_method_id(method_id)) { |
| ReportJNIFatalError(thr, fatal_non_weak_method); |
| } |
| return moop; |
| } |
| |
| |
| oop jniCheck::validate_object(JavaThread* thr, jobject obj) { |
| if (!obj) |
| return NULL; |
| ASSERT_OOPS_ALLOWED; |
| oop oopObj = jniCheck::validate_handle(thr, obj); |
| if (!oopObj) { |
| ReportJNIFatalError(thr, fatal_bad_ref_to_jni); |
| } |
| return oopObj; |
| } |
| |
| // Warn if a class descriptor is in decorated form; class descriptors |
| // passed to JNI findClass should not be decorated unless they are |
| // array descriptors. |
| void jniCheck::validate_class_descriptor(JavaThread* thr, const char* name) { |
| if (name == NULL) return; // implementation accepts NULL so just return |
| |
| size_t len = strlen(name); |
| |
| if (len >= 2 && |
| name[0] == JVM_SIGNATURE_CLASS && // 'L' |
| name[len-1] == JVM_SIGNATURE_ENDCLASS ) { // ';' |
| char msg[JVM_MAXPATHLEN]; |
| jio_snprintf(msg, JVM_MAXPATHLEN, "%s%s%s", |
| warn_bad_class_descriptor1, name, warn_bad_class_descriptor2); |
| ReportJNIWarning(thr, msg); |
| } |
| } |
| |
| Klass* jniCheck::validate_class(JavaThread* thr, jclass clazz, bool allow_primitive) { |
| ASSERT_OOPS_ALLOWED; |
| oop mirror = jniCheck::validate_handle(thr, clazz); |
| if (!mirror) { |
| ReportJNIFatalError(thr, fatal_received_null_class); |
| } |
| |
| if (mirror->klass() != SystemDictionary::Class_klass()) { |
| ReportJNIFatalError(thr, fatal_class_not_a_class); |
| } |
| |
| Klass* k = java_lang_Class::as_Klass(mirror); |
| // Make allowances for primitive classes ... |
| if (!(k != NULL || (allow_primitive && java_lang_Class::is_primitive(mirror)))) { |
| ReportJNIFatalError(thr, fatal_class_not_a_class); |
| } |
| return k; |
| } |
| |
| void jniCheck::validate_throwable_klass(JavaThread* thr, Klass* klass) { |
| ASSERT_OOPS_ALLOWED; |
| assert(klass != NULL, "klass argument must have a value"); |
| |
| if (!klass->is_instance_klass() || |
| !InstanceKlass::cast(klass)->is_subclass_of(SystemDictionary::Throwable_klass())) { |
| ReportJNIFatalError(thr, fatal_class_not_a_throwable_class); |
| } |
| } |
| |
| void jniCheck::validate_call_object(JavaThread* thr, jobject obj, jmethodID method_id) { |
| /* validate the object being passed */ |
| ASSERT_OOPS_ALLOWED; |
| jniCheck::validate_jmethod_id(thr, method_id); |
| jniCheck::validate_object(thr, obj); |
| } |
| |
| void jniCheck::validate_call_class(JavaThread* thr, jclass clazz, jmethodID method_id) { |
| /* validate the class being passed */ |
| ASSERT_OOPS_ALLOWED; |
| jniCheck::validate_jmethod_id(thr, method_id); |
| jniCheck::validate_class(thr, clazz, false); |
| } |
| |
| |
| /* |
| * IMPLEMENTATION OF FUNCTIONS IN CHECKED TABLE |
| */ |
| |
| JNI_ENTRY_CHECKED(jclass, |
| checked_jni_DefineClass(JNIEnv *env, |
| const char *name, |
| jobject loader, |
| const jbyte *buf, |
| jsize len)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_object(thr, loader); |
| ) |
| jclass result = UNCHECKED()->DefineClass(env, name, loader, buf, len); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jclass, |
| checked_jni_FindClass(JNIEnv *env, |
| const char *name)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class_descriptor(thr, name); |
| ) |
| jclass result = UNCHECKED()->FindClass(env, name); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jmethodID, |
| checked_jni_FromReflectedMethod(JNIEnv *env, |
| jobject method)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_object(thr, method); |
| ) |
| jmethodID result = UNCHECKED()->FromReflectedMethod(env, method); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jfieldID, |
| checked_jni_FromReflectedField(JNIEnv *env, |
| jobject field)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_object(thr, field); |
| ) |
| jfieldID result = UNCHECKED()->FromReflectedField(env, field); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_ToReflectedMethod(JNIEnv *env, |
| jclass cls, |
| jmethodID methodID, |
| jboolean isStatic)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, cls, false); |
| jniCheck::validate_jmethod_id(thr, methodID); |
| ) |
| jobject result = UNCHECKED()->ToReflectedMethod(env, cls, methodID, |
| isStatic); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jclass, |
| checked_jni_GetSuperclass(JNIEnv *env, |
| jclass sub)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, sub, true); |
| ) |
| jclass result = UNCHECKED()->GetSuperclass(env, sub); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jboolean, |
| checked_jni_IsAssignableFrom(JNIEnv *env, |
| jclass sub, |
| jclass sup)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, sub, true); |
| jniCheck::validate_class(thr, sup, true); |
| ) |
| jboolean result = UNCHECKED()->IsAssignableFrom(env, sub, sup); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_ToReflectedField(JNIEnv *env, |
| jclass cls, |
| jfieldID fieldID, |
| jboolean isStatic)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, cls, false); |
| ) |
| jobject result = UNCHECKED()->ToReflectedField(env, cls, fieldID, |
| isStatic); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_Throw(JNIEnv *env, |
| jthrowable obj)) |
| functionEnter(thr); |
| IN_VM( |
| oop oopObj = jniCheck::validate_object(thr, obj); |
| if (oopObj == NULL) { |
| // Unchecked Throw tolerates a NULL obj, so just warn |
| ReportJNIWarning(thr, "JNI Throw called with NULL throwable"); |
| } else { |
| jniCheck::validate_throwable_klass(thr, oopObj->klass()); |
| } |
| ) |
| jint result = UNCHECKED()->Throw(env, obj); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_ThrowNew(JNIEnv *env, |
| jclass clazz, |
| const char *msg)) |
| functionEnter(thr); |
| IN_VM( |
| Klass* k = jniCheck::validate_class(thr, clazz, false); |
| assert(k != NULL, "validate_class shouldn't return NULL Klass*"); |
| jniCheck::validate_throwable_klass(thr, k); |
| ) |
| jint result = UNCHECKED()->ThrowNew(env, clazz, msg); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jthrowable, |
| checked_jni_ExceptionOccurred(JNIEnv *env)) |
| thr->clear_pending_jni_exception_check(); |
| functionEnterExceptionAllowed(thr); |
| jthrowable result = UNCHECKED()->ExceptionOccurred(env); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_ExceptionDescribe(JNIEnv *env)) |
| functionEnterExceptionAllowed(thr); |
| UNCHECKED()->ExceptionDescribe(env); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_ExceptionClear(JNIEnv *env)) |
| thr->clear_pending_jni_exception_check(); |
| functionEnterExceptionAllowed(thr); |
| UNCHECKED()->ExceptionClear(env); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_FatalError(JNIEnv *env, |
| const char *msg)) |
| thr->clear_pending_jni_exception_check(); |
| functionEnter(thr); |
| UNCHECKED()->FatalError(env, msg); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_PushLocalFrame(JNIEnv *env, |
| jint capacity)) |
| functionEnterExceptionAllowed(thr); |
| if (capacity < 0) |
| NativeReportJNIFatalError(thr, "negative capacity"); |
| jint result = UNCHECKED()->PushLocalFrame(env, capacity); |
| if (result == JNI_OK) { |
| add_planned_handle_capacity(thr->active_handles(), capacity); |
| } |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_PopLocalFrame(JNIEnv *env, |
| jobject result)) |
| functionEnterExceptionAllowed(thr); |
| jobject res = UNCHECKED()->PopLocalFrame(env, result); |
| functionExit(thr); |
| return res; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_NewGlobalRef(JNIEnv *env, |
| jobject lobj)) |
| functionEnter(thr); |
| IN_VM( |
| if (lobj != NULL) { |
| jniCheck::validate_handle(thr, lobj); |
| } |
| ) |
| jobject result = UNCHECKED()->NewGlobalRef(env,lobj); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_DeleteGlobalRef(JNIEnv *env, |
| jobject gref)) |
| functionEnterExceptionAllowed(thr); |
| IN_VM( |
| jniCheck::validate_object(thr, gref); |
| if (gref && !JNIHandles::is_global_handle(gref)) { |
| ReportJNIFatalError(thr, |
| "Invalid global JNI handle passed to DeleteGlobalRef"); |
| } |
| ) |
| UNCHECKED()->DeleteGlobalRef(env,gref); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_DeleteLocalRef(JNIEnv *env, |
| jobject obj)) |
| functionEnterExceptionAllowed(thr); |
| IN_VM( |
| jniCheck::validate_object(thr, obj); |
| if (obj && !(JNIHandles::is_local_handle(thr, obj) || |
| JNIHandles::is_frame_handle(thr, obj))) |
| ReportJNIFatalError(thr, |
| "Invalid local JNI handle passed to DeleteLocalRef"); |
| ) |
| UNCHECKED()->DeleteLocalRef(env, obj); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jboolean, |
| checked_jni_IsSameObject(JNIEnv *env, |
| jobject obj1, |
| jobject obj2)) |
| functionEnterExceptionAllowed(thr); |
| IN_VM( |
| /* This JNI function can be used to compare weak global references |
| * to NULL objects. If the handles are valid, but contain NULL, |
| * then don't attempt to validate the object. |
| */ |
| if (obj1 != NULL && jniCheck::validate_handle(thr, obj1) != NULL) { |
| jniCheck::validate_object(thr, obj1); |
| } |
| if (obj2 != NULL && jniCheck::validate_handle(thr, obj2) != NULL) { |
| jniCheck::validate_object(thr, obj2); |
| } |
| ) |
| jboolean result = UNCHECKED()->IsSameObject(env,obj1,obj2); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_NewLocalRef(JNIEnv *env, |
| jobject ref)) |
| functionEnter(thr); |
| IN_VM( |
| if (ref != NULL) { |
| jniCheck::validate_handle(thr, ref); |
| } |
| ) |
| jobject result = UNCHECKED()->NewLocalRef(env, ref); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_EnsureLocalCapacity(JNIEnv *env, |
| jint capacity)) |
| functionEnter(thr); |
| if (capacity < 0) { |
| NativeReportJNIFatalError(thr, "negative capacity"); |
| } |
| jint result = UNCHECKED()->EnsureLocalCapacity(env, capacity); |
| if (result == JNI_OK) { |
| add_planned_handle_capacity(thr->active_handles(), capacity); |
| } |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_AllocObject(JNIEnv *env, |
| jclass clazz)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, clazz, false); |
| ) |
| jobject result = UNCHECKED()->AllocObject(env,clazz); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_NewObject(JNIEnv *env, |
| jclass clazz, |
| jmethodID methodID, |
| ...)) |
| functionEnter(thr); |
| va_list args; |
| IN_VM( |
| jniCheck::validate_class(thr, clazz, false); |
| jniCheck::validate_jmethod_id(thr, methodID); |
| ) |
| va_start(args, methodID); |
| jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args); |
| va_end(args); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_NewObjectV(JNIEnv *env, |
| jclass clazz, |
| jmethodID methodID, |
| va_list args)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, clazz, false); |
| jniCheck::validate_jmethod_id(thr, methodID); |
| ) |
| jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_NewObjectA(JNIEnv *env, |
| jclass clazz, |
| jmethodID methodID, |
| const jvalue *args)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, clazz, false); |
| jniCheck::validate_jmethod_id(thr, methodID); |
| ) |
| jobject result = UNCHECKED()->NewObjectA(env,clazz,methodID,args); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jclass, |
| checked_jni_GetObjectClass(JNIEnv *env, |
| jobject obj)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_object(thr, obj); |
| ) |
| jclass result = UNCHECKED()->GetObjectClass(env,obj); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jboolean, |
| checked_jni_IsInstanceOf(JNIEnv *env, |
| jobject obj, |
| jclass clazz)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_object(thr, obj); |
| jniCheck::validate_class(thr, clazz, true); |
| ) |
| jboolean result = UNCHECKED()->IsInstanceOf(env,obj,clazz); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jmethodID, |
| checked_jni_GetMethodID(JNIEnv *env, |
| jclass clazz, |
| const char *name, |
| const char *sig)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, clazz, false); |
| ) |
| jmethodID result = UNCHECKED()->GetMethodID(env,clazz,name,sig); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| #define WRAPPER_CallMethod(ResultType, Result) \ |
| JNI_ENTRY_CHECKED(ResultType, \ |
| checked_jni_Call##Result##Method(JNIEnv *env, \ |
| jobject obj, \ |
| jmethodID methodID, \ |
| ...)) \ |
| functionEnter(thr); \ |
| va_list args; \ |
| IN_VM( \ |
| jniCheck::validate_call_object(thr, obj, methodID); \ |
| ) \ |
| va_start(args,methodID); \ |
| ResultType result =UNCHECKED()->Call##Result##MethodV(env, obj, methodID, \ |
| args); \ |
| va_end(args); \ |
| thr->set_pending_jni_exception_check("Call"#Result"Method"); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END \ |
| \ |
| JNI_ENTRY_CHECKED(ResultType, \ |
| checked_jni_Call##Result##MethodV(JNIEnv *env, \ |
| jobject obj, \ |
| jmethodID methodID, \ |
| va_list args)) \ |
| functionEnter(thr); \ |
| IN_VM(\ |
| jniCheck::validate_call_object(thr, obj, methodID); \ |
| ) \ |
| ResultType result = UNCHECKED()->Call##Result##MethodV(env, obj, methodID,\ |
| args); \ |
| thr->set_pending_jni_exception_check("Call"#Result"MethodV"); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END \ |
| \ |
| JNI_ENTRY_CHECKED(ResultType, \ |
| checked_jni_Call##Result##MethodA(JNIEnv *env, \ |
| jobject obj, \ |
| jmethodID methodID, \ |
| const jvalue * args)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| jniCheck::validate_call_object(thr, obj, methodID); \ |
| ) \ |
| ResultType result = UNCHECKED()->Call##Result##MethodA(env, obj, methodID,\ |
| args); \ |
| thr->set_pending_jni_exception_check("Call"#Result"MethodA"); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END |
| |
| WRAPPER_CallMethod(jobject,Object) |
| WRAPPER_CallMethod(jboolean,Boolean) |
| WRAPPER_CallMethod(jbyte,Byte) |
| WRAPPER_CallMethod(jshort,Short) |
| WRAPPER_CallMethod(jchar,Char) |
| WRAPPER_CallMethod(jint,Int) |
| WRAPPER_CallMethod(jlong,Long) |
| WRAPPER_CallMethod(jfloat,Float) |
| WRAPPER_CallMethod(jdouble,Double) |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_CallVoidMethod(JNIEnv *env, \ |
| jobject obj, \ |
| jmethodID methodID, \ |
| ...)) |
| functionEnter(thr); |
| va_list args; |
| IN_VM( |
| jniCheck::validate_call_object(thr, obj, methodID); |
| ) |
| va_start(args,methodID); |
| UNCHECKED()->CallVoidMethodV(env,obj,methodID,args); |
| va_end(args); |
| thr->set_pending_jni_exception_check("CallVoidMethod"); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_CallVoidMethodV(JNIEnv *env, |
| jobject obj, |
| jmethodID methodID, |
| va_list args)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_call_object(thr, obj, methodID); |
| ) |
| UNCHECKED()->CallVoidMethodV(env,obj,methodID,args); |
| thr->set_pending_jni_exception_check("CallVoidMethodV"); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_CallVoidMethodA(JNIEnv *env, |
| jobject obj, |
| jmethodID methodID, |
| const jvalue * args)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_call_object(thr, obj, methodID); |
| ) |
| UNCHECKED()->CallVoidMethodA(env,obj,methodID,args); |
| thr->set_pending_jni_exception_check("CallVoidMethodA"); |
| functionExit(thr); |
| JNI_END |
| |
| #define WRAPPER_CallNonvirtualMethod(ResultType, Result) \ |
| JNI_ENTRY_CHECKED(ResultType, \ |
| checked_jni_CallNonvirtual##Result##Method(JNIEnv *env, \ |
| jobject obj, \ |
| jclass clazz, \ |
| jmethodID methodID, \ |
| ...)) \ |
| functionEnter(thr); \ |
| va_list args; \ |
| IN_VM( \ |
| jniCheck::validate_call_object(thr, obj, methodID); \ |
| jniCheck::validate_call_class(thr, clazz, methodID); \ |
| ) \ |
| va_start(args,methodID); \ |
| ResultType result = UNCHECKED()->CallNonvirtual##Result##MethodV(env, \ |
| obj, \ |
| clazz, \ |
| methodID,\ |
| args); \ |
| va_end(args); \ |
| thr->set_pending_jni_exception_check("CallNonvirtual"#Result"Method"); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END \ |
| \ |
| JNI_ENTRY_CHECKED(ResultType, \ |
| checked_jni_CallNonvirtual##Result##MethodV(JNIEnv *env, \ |
| jobject obj, \ |
| jclass clazz, \ |
| jmethodID methodID, \ |
| va_list args)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| jniCheck::validate_call_object(thr, obj, methodID); \ |
| jniCheck::validate_call_class(thr, clazz, methodID); \ |
| ) \ |
| ResultType result = UNCHECKED()->CallNonvirtual##Result##MethodV(env, \ |
| obj, \ |
| clazz, \ |
| methodID,\ |
| args); \ |
| thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodV"); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END \ |
| \ |
| JNI_ENTRY_CHECKED(ResultType, \ |
| checked_jni_CallNonvirtual##Result##MethodA(JNIEnv *env, \ |
| jobject obj, \ |
| jclass clazz, \ |
| jmethodID methodID, \ |
| const jvalue * args)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| jniCheck::validate_call_object(thr, obj, methodID); \ |
| jniCheck::validate_call_class(thr, clazz, methodID); \ |
| ) \ |
| ResultType result = UNCHECKED()->CallNonvirtual##Result##MethodA(env, \ |
| obj, \ |
| clazz, \ |
| methodID,\ |
| args); \ |
| thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodA"); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END |
| |
| WRAPPER_CallNonvirtualMethod(jobject,Object) |
| WRAPPER_CallNonvirtualMethod(jboolean,Boolean) |
| WRAPPER_CallNonvirtualMethod(jbyte,Byte) |
| WRAPPER_CallNonvirtualMethod(jshort,Short) |
| WRAPPER_CallNonvirtualMethod(jchar,Char) |
| WRAPPER_CallNonvirtualMethod(jint,Int) |
| WRAPPER_CallNonvirtualMethod(jlong,Long) |
| WRAPPER_CallNonvirtualMethod(jfloat,Float) |
| WRAPPER_CallNonvirtualMethod(jdouble,Double) |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_CallNonvirtualVoidMethod(JNIEnv *env, |
| jobject obj, |
| jclass clazz, |
| jmethodID methodID, |
| ...)) |
| functionEnter(thr); |
| va_list args; |
| IN_VM( |
| jniCheck::validate_call_object(thr, obj, methodID); |
| jniCheck::validate_call_class(thr, clazz, methodID); |
| ) |
| va_start(args,methodID); |
| UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args); |
| va_end(args); |
| thr->set_pending_jni_exception_check("CallNonvirtualVoidMethod"); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_CallNonvirtualVoidMethodV(JNIEnv *env, |
| jobject obj, |
| jclass clazz, |
| jmethodID methodID, |
| va_list args)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_call_object(thr, obj, methodID); |
| jniCheck::validate_call_class(thr, clazz, methodID); |
| ) |
| UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args); |
| thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodV"); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_CallNonvirtualVoidMethodA(JNIEnv *env, |
| jobject obj, |
| jclass clazz, |
| jmethodID methodID, |
| const jvalue * args)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_call_object(thr, obj, methodID); |
| jniCheck::validate_call_class(thr, clazz, methodID); |
| ) |
| UNCHECKED()->CallNonvirtualVoidMethodA(env,obj,clazz,methodID,args); |
| thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodA"); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jfieldID, |
| checked_jni_GetFieldID(JNIEnv *env, |
| jclass clazz, |
| const char *name, |
| const char *sig)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, clazz, false); |
| ) |
| jfieldID result = UNCHECKED()->GetFieldID(env,clazz,name,sig); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| #define WRAPPER_GetField(ReturnType,Result,FieldType) \ |
| JNI_ENTRY_CHECKED(ReturnType, \ |
| checked_jni_Get##Result##Field(JNIEnv *env, \ |
| jobject obj, \ |
| jfieldID fieldID)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| checkInstanceFieldID(thr, fieldID, obj, FieldType); \ |
| ) \ |
| ReturnType result = UNCHECKED()->Get##Result##Field(env,obj,fieldID); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END |
| |
| WRAPPER_GetField(jobject, Object, T_OBJECT) |
| WRAPPER_GetField(jboolean, Boolean, T_BOOLEAN) |
| WRAPPER_GetField(jbyte, Byte, T_BYTE) |
| WRAPPER_GetField(jshort, Short, T_SHORT) |
| WRAPPER_GetField(jchar, Char, T_CHAR) |
| WRAPPER_GetField(jint, Int, T_INT) |
| WRAPPER_GetField(jlong, Long, T_LONG) |
| WRAPPER_GetField(jfloat, Float, T_FLOAT) |
| WRAPPER_GetField(jdouble, Double, T_DOUBLE) |
| |
| #define WRAPPER_SetField(ValueType,Result,FieldType) \ |
| JNI_ENTRY_CHECKED(void, \ |
| checked_jni_Set##Result##Field(JNIEnv *env, \ |
| jobject obj, \ |
| jfieldID fieldID, \ |
| ValueType val)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| checkInstanceFieldID(thr, fieldID, obj, FieldType); \ |
| ) \ |
| UNCHECKED()->Set##Result##Field(env,obj,fieldID,val); \ |
| functionExit(thr); \ |
| JNI_END |
| |
| WRAPPER_SetField(jobject, Object, T_OBJECT) |
| WRAPPER_SetField(jboolean, Boolean, T_BOOLEAN) |
| WRAPPER_SetField(jbyte, Byte, T_BYTE) |
| WRAPPER_SetField(jshort, Short, T_SHORT) |
| WRAPPER_SetField(jchar, Char, T_CHAR) |
| WRAPPER_SetField(jint, Int, T_INT) |
| WRAPPER_SetField(jlong, Long, T_LONG) |
| WRAPPER_SetField(jfloat, Float, T_FLOAT) |
| WRAPPER_SetField(jdouble, Double, T_DOUBLE) |
| |
| |
| JNI_ENTRY_CHECKED(jmethodID, |
| checked_jni_GetStaticMethodID(JNIEnv *env, |
| jclass clazz, |
| const char *name, |
| const char *sig)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, clazz, false); |
| ) |
| jmethodID result = UNCHECKED()->GetStaticMethodID(env,clazz,name,sig); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| #define WRAPPER_CallStaticMethod(ReturnType,Result) \ |
| JNI_ENTRY_CHECKED(ReturnType, \ |
| checked_jni_CallStatic##Result##Method(JNIEnv *env, \ |
| jclass clazz, \ |
| jmethodID methodID, \ |
| ...)) \ |
| functionEnter(thr); \ |
| va_list args; \ |
| IN_VM( \ |
| jniCheck::validate_jmethod_id(thr, methodID); \ |
| jniCheck::validate_class(thr, clazz, false); \ |
| ) \ |
| va_start(args,methodID); \ |
| ReturnType result = UNCHECKED()->CallStatic##Result##MethodV(env, \ |
| clazz, \ |
| methodID, \ |
| args); \ |
| va_end(args); \ |
| thr->set_pending_jni_exception_check("CallStatic"#Result"Method"); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END \ |
| \ |
| JNI_ENTRY_CHECKED(ReturnType, \ |
| checked_jni_CallStatic##Result##MethodV(JNIEnv *env, \ |
| jclass clazz, \ |
| jmethodID methodID,\ |
| va_list args)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| jniCheck::validate_jmethod_id(thr, methodID); \ |
| jniCheck::validate_class(thr, clazz, false); \ |
| ) \ |
| ReturnType result = UNCHECKED()->CallStatic##Result##MethodV(env, \ |
| clazz, \ |
| methodID, \ |
| args); \ |
| thr->set_pending_jni_exception_check("CallStatic"#Result"MethodV"); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END \ |
| \ |
| JNI_ENTRY_CHECKED(ReturnType, \ |
| checked_jni_CallStatic##Result##MethodA(JNIEnv *env, \ |
| jclass clazz, \ |
| jmethodID methodID, \ |
| const jvalue *args)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| jniCheck::validate_jmethod_id(thr, methodID); \ |
| jniCheck::validate_class(thr, clazz, false); \ |
| ) \ |
| ReturnType result = UNCHECKED()->CallStatic##Result##MethodA(env, \ |
| clazz, \ |
| methodID, \ |
| args); \ |
| thr->set_pending_jni_exception_check("CallStatic"#Result"MethodA"); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END |
| |
| WRAPPER_CallStaticMethod(jobject,Object) |
| WRAPPER_CallStaticMethod(jboolean,Boolean) |
| WRAPPER_CallStaticMethod(jbyte,Byte) |
| WRAPPER_CallStaticMethod(jshort,Short) |
| WRAPPER_CallStaticMethod(jchar,Char) |
| WRAPPER_CallStaticMethod(jint,Int) |
| WRAPPER_CallStaticMethod(jlong,Long) |
| WRAPPER_CallStaticMethod(jfloat,Float) |
| WRAPPER_CallStaticMethod(jdouble,Double) |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_CallStaticVoidMethod(JNIEnv *env, |
| jclass cls, |
| jmethodID methodID, |
| ...)) |
| functionEnter(thr); |
| va_list args; |
| IN_VM( |
| jniCheck::validate_jmethod_id(thr, methodID); |
| jniCheck::validate_class(thr, cls, false); |
| ) |
| va_start(args,methodID); |
| UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args); |
| va_end(args); |
| thr->set_pending_jni_exception_check("CallStaticVoidMethod"); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_CallStaticVoidMethodV(JNIEnv *env, |
| jclass cls, |
| jmethodID methodID, |
| va_list args)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_jmethod_id(thr, methodID); |
| jniCheck::validate_class(thr, cls, false); |
| ) |
| UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args); |
| thr->set_pending_jni_exception_check("CallStaticVoidMethodV"); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_CallStaticVoidMethodA(JNIEnv *env, |
| jclass cls, |
| jmethodID methodID, |
| const jvalue * args)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_jmethod_id(thr, methodID); |
| jniCheck::validate_class(thr, cls, false); |
| ) |
| UNCHECKED()->CallStaticVoidMethodA(env,cls,methodID,args); |
| thr->set_pending_jni_exception_check("CallStaticVoidMethodA"); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jfieldID, |
| checked_jni_GetStaticFieldID(JNIEnv *env, |
| jclass clazz, |
| const char *name, |
| const char *sig)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, clazz, false); |
| ) |
| jfieldID result = UNCHECKED()->GetStaticFieldID(env,clazz,name,sig); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| #define WRAPPER_GetStaticField(ReturnType,Result,FieldType) \ |
| JNI_ENTRY_CHECKED(ReturnType, \ |
| checked_jni_GetStatic##Result##Field(JNIEnv *env, \ |
| jclass clazz, \ |
| jfieldID fieldID)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| jniCheck::validate_class(thr, clazz, false); \ |
| checkStaticFieldID(thr, fieldID, clazz, FieldType); \ |
| ) \ |
| ReturnType result = UNCHECKED()->GetStatic##Result##Field(env, \ |
| clazz, \ |
| fieldID); \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END |
| |
| WRAPPER_GetStaticField(jobject, Object, T_OBJECT) |
| WRAPPER_GetStaticField(jboolean, Boolean, T_BOOLEAN) |
| WRAPPER_GetStaticField(jbyte, Byte, T_BYTE) |
| WRAPPER_GetStaticField(jshort, Short, T_SHORT) |
| WRAPPER_GetStaticField(jchar, Char, T_CHAR) |
| WRAPPER_GetStaticField(jint, Int, T_INT) |
| WRAPPER_GetStaticField(jlong, Long, T_LONG) |
| WRAPPER_GetStaticField(jfloat, Float, T_FLOAT) |
| WRAPPER_GetStaticField(jdouble, Double, T_DOUBLE) |
| |
| #define WRAPPER_SetStaticField(ValueType,Result,FieldType) \ |
| JNI_ENTRY_CHECKED(void, \ |
| checked_jni_SetStatic##Result##Field(JNIEnv *env, \ |
| jclass clazz, \ |
| jfieldID fieldID, \ |
| ValueType value)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| jniCheck::validate_class(thr, clazz, false); \ |
| checkStaticFieldID(thr, fieldID, clazz, FieldType); \ |
| ) \ |
| UNCHECKED()->SetStatic##Result##Field(env,clazz,fieldID,value); \ |
| functionExit(thr); \ |
| JNI_END |
| |
| WRAPPER_SetStaticField(jobject, Object, T_OBJECT) |
| WRAPPER_SetStaticField(jboolean, Boolean, T_BOOLEAN) |
| WRAPPER_SetStaticField(jbyte, Byte, T_BYTE) |
| WRAPPER_SetStaticField(jshort, Short, T_SHORT) |
| WRAPPER_SetStaticField(jchar, Char, T_CHAR) |
| WRAPPER_SetStaticField(jint, Int, T_INT) |
| WRAPPER_SetStaticField(jlong, Long, T_LONG) |
| WRAPPER_SetStaticField(jfloat, Float, T_FLOAT) |
| WRAPPER_SetStaticField(jdouble, Double, T_DOUBLE) |
| |
| |
| JNI_ENTRY_CHECKED(jstring, |
| checked_jni_NewString(JNIEnv *env, |
| const jchar *unicode, |
| jsize len)) |
| functionEnter(thr); |
| jstring result = UNCHECKED()->NewString(env,unicode,len); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jsize, |
| checked_jni_GetStringLength(JNIEnv *env, |
| jstring str)) |
| functionEnter(thr); |
| IN_VM( |
| checkString(thr, str); |
| ) |
| jsize result = UNCHECKED()->GetStringLength(env,str); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| // Arbitrary (but well-known) tag |
| const void* STRING_TAG = (void*)0x47114711; |
| |
| JNI_ENTRY_CHECKED(const jchar *, |
| checked_jni_GetStringChars(JNIEnv *env, |
| jstring str, |
| jboolean *isCopy)) |
| functionEnter(thr); |
| IN_VM( |
| checkString(thr, str); |
| ) |
| jchar* new_result = NULL; |
| const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy); |
| assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected"); |
| if (result != NULL) { |
| size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination |
| len *= sizeof(jchar); |
| new_result = (jchar*) GuardedMemory::wrap_copy(result, len, STRING_TAG); |
| if (new_result == NULL) { |
| vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringChars"); |
| } |
| // Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes |
| // Note that the dtrace arguments for the allocated memory will not match up with this solution. |
| FreeHeap((char*)result); |
| } |
| functionExit(thr); |
| return new_result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_ReleaseStringChars(JNIEnv *env, |
| jstring str, |
| const jchar *chars)) |
| functionEnterExceptionAllowed(thr); |
| IN_VM( |
| checkString(thr, str); |
| ) |
| if (chars == NULL) { |
| // still do the unchecked call to allow dtrace probes |
| UNCHECKED()->ReleaseStringChars(env,str,chars); |
| } |
| else { |
| GuardedMemory guarded((void*)chars); |
| if (!guarded.verify_guards()) { |
| tty->print_cr("ReleaseStringChars: release chars failed bounds check. " |
| "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars)); |
| guarded.print_on(tty); |
| NativeReportJNIFatalError(thr, "ReleaseStringChars: " |
| "release chars failed bounds check."); |
| } |
| if (guarded.get_tag() != STRING_TAG) { |
| tty->print_cr("ReleaseStringChars: called on something not allocated " |
| "by GetStringChars. string: " PTR_FORMAT " chars: " PTR_FORMAT, |
| p2i(str), p2i(chars)); |
| NativeReportJNIFatalError(thr, "ReleaseStringChars called on something " |
| "not allocated by GetStringChars"); |
| } |
| UNCHECKED()->ReleaseStringChars(env, str, |
| (const jchar*) guarded.release_for_freeing()); |
| } |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jstring, |
| checked_jni_NewStringUTF(JNIEnv *env, |
| const char *utf)) |
| functionEnter(thr); |
| jstring result = UNCHECKED()->NewStringUTF(env,utf); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jsize, |
| checked_jni_GetStringUTFLength(JNIEnv *env, |
| jstring str)) |
| functionEnter(thr); |
| IN_VM( |
| checkString(thr, str); |
| ) |
| jsize result = UNCHECKED()->GetStringUTFLength(env,str); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| // Arbitrary (but well-known) tag - different than GetStringChars |
| const void* STRING_UTF_TAG = (void*) 0x48124812; |
| |
| JNI_ENTRY_CHECKED(const char *, |
| checked_jni_GetStringUTFChars(JNIEnv *env, |
| jstring str, |
| jboolean *isCopy)) |
| functionEnter(thr); |
| IN_VM( |
| checkString(thr, str); |
| ) |
| char* new_result = NULL; |
| const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy); |
| assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected"); |
| if (result != NULL) { |
| size_t len = strlen(result) + 1; // + 1 for NULL termination |
| new_result = (char*) GuardedMemory::wrap_copy(result, len, STRING_UTF_TAG); |
| if (new_result == NULL) { |
| vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringUTFChars"); |
| } |
| // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes |
| // Note that the dtrace arguments for the allocated memory will not match up with this solution. |
| FreeHeap((char*)result); |
| } |
| functionExit(thr); |
| return new_result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_ReleaseStringUTFChars(JNIEnv *env, |
| jstring str, |
| const char* chars)) |
| functionEnterExceptionAllowed(thr); |
| IN_VM( |
| checkString(thr, str); |
| ) |
| if (chars == NULL) { |
| // still do the unchecked call to allow dtrace probes |
| UNCHECKED()->ReleaseStringUTFChars(env,str,chars); |
| } |
| else { |
| GuardedMemory guarded((void*)chars); |
| if (!guarded.verify_guards()) { |
| tty->print_cr("ReleaseStringUTFChars: release chars failed bounds check. " |
| "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars)); |
| guarded.print_on(tty); |
| NativeReportJNIFatalError(thr, "ReleaseStringUTFChars: " |
| "release chars failed bounds check."); |
| } |
| if (guarded.get_tag() != STRING_UTF_TAG) { |
| tty->print_cr("ReleaseStringUTFChars: called on something not " |
| "allocated by GetStringUTFChars. string: " PTR_FORMAT " chars: " |
| PTR_FORMAT, p2i(str), p2i(chars)); |
| NativeReportJNIFatalError(thr, "ReleaseStringUTFChars " |
| "called on something not allocated by GetStringUTFChars"); |
| } |
| UNCHECKED()->ReleaseStringUTFChars(env, str, |
| (const char*) guarded.release_for_freeing()); |
| } |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jsize, |
| checked_jni_GetArrayLength(JNIEnv *env, |
| jarray array)) |
| functionEnter(thr); |
| IN_VM( |
| check_is_array(thr, array); |
| ) |
| jsize result = UNCHECKED()->GetArrayLength(env,array); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobjectArray, |
| checked_jni_NewObjectArray(JNIEnv *env, |
| jsize len, |
| jclass clazz, |
| jobject init)) |
| functionEnter(thr); |
| jobjectArray result = UNCHECKED()->NewObjectArray(env,len,clazz,init); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_GetObjectArrayElement(JNIEnv *env, |
| jobjectArray array, |
| jsize index)) |
| functionEnter(thr); |
| IN_VM( |
| check_is_obj_array(thr, array); |
| ) |
| jobject result = UNCHECKED()->GetObjectArrayElement(env,array,index); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_SetObjectArrayElement(JNIEnv *env, |
| jobjectArray array, |
| jsize index, |
| jobject val)) |
| functionEnter(thr); |
| IN_VM( |
| check_is_obj_array(thr, array); |
| ) |
| UNCHECKED()->SetObjectArrayElement(env,array,index,val); |
| functionExit(thr); |
| JNI_END |
| |
| #define WRAPPER_NewScalarArray(Return, Result) \ |
| JNI_ENTRY_CHECKED(Return, \ |
| checked_jni_New##Result##Array(JNIEnv *env, \ |
| jsize len)) \ |
| functionEnter(thr); \ |
| Return result = UNCHECKED()->New##Result##Array(env,len); \ |
| functionExit(thr); \ |
| return (Return) result; \ |
| JNI_END |
| |
| WRAPPER_NewScalarArray(jbooleanArray, Boolean) |
| WRAPPER_NewScalarArray(jbyteArray, Byte) |
| WRAPPER_NewScalarArray(jshortArray, Short) |
| WRAPPER_NewScalarArray(jcharArray, Char) |
| WRAPPER_NewScalarArray(jintArray, Int) |
| WRAPPER_NewScalarArray(jlongArray, Long) |
| WRAPPER_NewScalarArray(jfloatArray, Float) |
| WRAPPER_NewScalarArray(jdoubleArray, Double) |
| |
| #define WRAPPER_GetScalarArrayElements(ElementTag,ElementType,Result) \ |
| JNI_ENTRY_CHECKED(ElementType *, \ |
| checked_jni_Get##Result##ArrayElements(JNIEnv *env, \ |
| ElementType##Array array, \ |
| jboolean *isCopy)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| check_primitive_array_type(thr, array, ElementTag); \ |
| ) \ |
| ElementType *result = UNCHECKED()->Get##Result##ArrayElements(env, \ |
| array, \ |
| isCopy); \ |
| if (result != NULL) { \ |
| result = (ElementType *) check_jni_wrap_copy_array(thr, array, result); \ |
| } \ |
| functionExit(thr); \ |
| return result; \ |
| JNI_END |
| |
| WRAPPER_GetScalarArrayElements(T_BOOLEAN, jboolean, Boolean) |
| WRAPPER_GetScalarArrayElements(T_BYTE, jbyte, Byte) |
| WRAPPER_GetScalarArrayElements(T_SHORT, jshort, Short) |
| WRAPPER_GetScalarArrayElements(T_CHAR, jchar, Char) |
| WRAPPER_GetScalarArrayElements(T_INT, jint, Int) |
| WRAPPER_GetScalarArrayElements(T_LONG, jlong, Long) |
| WRAPPER_GetScalarArrayElements(T_FLOAT, jfloat, Float) |
| WRAPPER_GetScalarArrayElements(T_DOUBLE, jdouble, Double) |
| |
| #define WRAPPER_ReleaseScalarArrayElements(ElementTag,ElementType,Result,Tag) \ |
| JNI_ENTRY_CHECKED(void, \ |
| checked_jni_Release##Result##ArrayElements(JNIEnv *env, \ |
| ElementType##Array array, \ |
| ElementType *elems, \ |
| jint mode)) \ |
| functionEnterExceptionAllowed(thr); \ |
| IN_VM( \ |
| check_primitive_array_type(thr, array, ElementTag); \ |
| ASSERT_OOPS_ALLOWED; \ |
| typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ |
| ) \ |
| ElementType* orig_result = (ElementType *) check_wrapped_array_release( \ |
| thr, "checked_jni_Release"#Result"ArrayElements", array, elems, mode); \ |
| UNCHECKED()->Release##Result##ArrayElements(env, array, orig_result, mode); \ |
| functionExit(thr); \ |
| JNI_END |
| |
| WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool) |
| WRAPPER_ReleaseScalarArrayElements(T_BYTE, jbyte, Byte, byte) |
| WRAPPER_ReleaseScalarArrayElements(T_SHORT, jshort, Short, short) |
| WRAPPER_ReleaseScalarArrayElements(T_CHAR, jchar, Char, char) |
| WRAPPER_ReleaseScalarArrayElements(T_INT, jint, Int, int) |
| WRAPPER_ReleaseScalarArrayElements(T_LONG, jlong, Long, long) |
| WRAPPER_ReleaseScalarArrayElements(T_FLOAT, jfloat, Float, float) |
| WRAPPER_ReleaseScalarArrayElements(T_DOUBLE, jdouble, Double, double) |
| |
| #define WRAPPER_GetScalarArrayRegion(ElementTag,ElementType,Result) \ |
| JNI_ENTRY_CHECKED(void, \ |
| checked_jni_Get##Result##ArrayRegion(JNIEnv *env, \ |
| ElementType##Array array, \ |
| jsize start, \ |
| jsize len, \ |
| ElementType *buf)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| check_primitive_array_type(thr, array, ElementTag); \ |
| ) \ |
| UNCHECKED()->Get##Result##ArrayRegion(env,array,start,len,buf); \ |
| functionExit(thr); \ |
| JNI_END |
| |
| WRAPPER_GetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean) |
| WRAPPER_GetScalarArrayRegion(T_BYTE, jbyte, Byte) |
| WRAPPER_GetScalarArrayRegion(T_SHORT, jshort, Short) |
| WRAPPER_GetScalarArrayRegion(T_CHAR, jchar, Char) |
| WRAPPER_GetScalarArrayRegion(T_INT, jint, Int) |
| WRAPPER_GetScalarArrayRegion(T_LONG, jlong, Long) |
| WRAPPER_GetScalarArrayRegion(T_FLOAT, jfloat, Float) |
| WRAPPER_GetScalarArrayRegion(T_DOUBLE, jdouble, Double) |
| |
| #define WRAPPER_SetScalarArrayRegion(ElementTag,ElementType,Result) \ |
| JNI_ENTRY_CHECKED(void, \ |
| checked_jni_Set##Result##ArrayRegion(JNIEnv *env, \ |
| ElementType##Array array, \ |
| jsize start, \ |
| jsize len, \ |
| const ElementType *buf)) \ |
| functionEnter(thr); \ |
| IN_VM( \ |
| check_primitive_array_type(thr, array, ElementTag); \ |
| ) \ |
| UNCHECKED()->Set##Result##ArrayRegion(env,array,start,len,buf); \ |
| functionExit(thr); \ |
| JNI_END |
| |
| WRAPPER_SetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean) |
| WRAPPER_SetScalarArrayRegion(T_BYTE, jbyte, Byte) |
| WRAPPER_SetScalarArrayRegion(T_SHORT, jshort, Short) |
| WRAPPER_SetScalarArrayRegion(T_CHAR, jchar, Char) |
| WRAPPER_SetScalarArrayRegion(T_INT, jint, Int) |
| WRAPPER_SetScalarArrayRegion(T_LONG, jlong, Long) |
| WRAPPER_SetScalarArrayRegion(T_FLOAT, jfloat, Float) |
| WRAPPER_SetScalarArrayRegion(T_DOUBLE, jdouble, Double) |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_RegisterNatives(JNIEnv *env, |
| jclass clazz, |
| const JNINativeMethod *methods, |
| jint nMethods)) |
| functionEnter(thr); |
| jint result = UNCHECKED()->RegisterNatives(env,clazz,methods,nMethods); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_UnregisterNatives(JNIEnv *env, |
| jclass clazz)) |
| functionEnter(thr); |
| jint result = UNCHECKED()->UnregisterNatives(env,clazz); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_MonitorEnter(JNIEnv *env, |
| jobject obj)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_object(thr, obj); |
| ) |
| jint result = UNCHECKED()->MonitorEnter(env,obj); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_MonitorExit(JNIEnv *env, |
| jobject obj)) |
| functionEnterExceptionAllowed(thr); |
| IN_VM( |
| jniCheck::validate_object(thr, obj); |
| ) |
| jint result = UNCHECKED()->MonitorExit(env,obj); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_GetJavaVM(JNIEnv *env, |
| JavaVM **vm)) |
| functionEnter(thr); |
| jint result = UNCHECKED()->GetJavaVM(env,vm); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_GetStringRegion(JNIEnv *env, |
| jstring str, |
| jsize start, |
| jsize len, |
| jchar *buf)) |
| functionEnter(thr); |
| IN_VM( |
| checkString(thr, str); |
| ) |
| UNCHECKED()->GetStringRegion(env, str, start, len, buf); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_GetStringUTFRegion(JNIEnv *env, |
| jstring str, |
| jsize start, |
| jsize len, |
| char *buf)) |
| functionEnter(thr); |
| IN_VM( |
| checkString(thr, str); |
| ) |
| UNCHECKED()->GetStringUTFRegion(env, str, start, len, buf); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void *, |
| checked_jni_GetPrimitiveArrayCritical(JNIEnv *env, |
| jarray array, |
| jboolean *isCopy)) |
| functionEnterCritical(thr); |
| IN_VM( |
| check_is_primitive_array(thr, array); |
| ) |
| void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy); |
| if (result != NULL) { |
| result = check_jni_wrap_copy_array(thr, array, result); |
| } |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_ReleasePrimitiveArrayCritical(JNIEnv *env, |
| jarray array, |
| void *carray, |
| jint mode)) |
| functionEnterCriticalExceptionAllowed(thr); |
| IN_VM( |
| check_is_primitive_array(thr, array); |
| ) |
| // Check the element array... |
| void* orig_result = check_wrapped_array_release(thr, "ReleasePrimitiveArrayCritical", array, carray, mode); |
| UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, orig_result, mode); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(const jchar*, |
| checked_jni_GetStringCritical(JNIEnv *env, |
| jstring string, |
| jboolean *isCopy)) |
| functionEnterCritical(thr); |
| IN_VM( |
| checkString(thr, string); |
| ) |
| const jchar *result = UNCHECKED()->GetStringCritical(env, string, isCopy); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_ReleaseStringCritical(JNIEnv *env, |
| jstring str, |
| const jchar *chars)) |
| functionEnterCriticalExceptionAllowed(thr); |
| IN_VM( |
| checkString(thr, str); |
| ) |
| /* The Hotspot JNI code does not use the parameters, so just check the |
| * string parameter as a minor sanity check |
| */ |
| UNCHECKED()->ReleaseStringCritical(env, str, chars); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jweak, |
| checked_jni_NewWeakGlobalRef(JNIEnv *env, |
| jobject obj)) |
| functionEnter(thr); |
| IN_VM( |
| if (obj != NULL) { |
| jniCheck::validate_handle(thr, obj); |
| } |
| ) |
| jweak result = UNCHECKED()->NewWeakGlobalRef(env, obj); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void, |
| checked_jni_DeleteWeakGlobalRef(JNIEnv *env, |
| jweak ref)) |
| functionEnterExceptionAllowed(thr); |
| UNCHECKED()->DeleteWeakGlobalRef(env, ref); |
| functionExit(thr); |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jboolean, |
| checked_jni_ExceptionCheck(JNIEnv *env)) |
| thr->clear_pending_jni_exception_check(); |
| functionEnterExceptionAllowed(thr); |
| jboolean result = UNCHECKED()->ExceptionCheck(env); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_NewDirectByteBuffer(JNIEnv *env, |
| void *address, |
| jlong capacity)) |
| functionEnter(thr); |
| jobject result = UNCHECKED()->NewDirectByteBuffer(env, address, capacity); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(void *, |
| checked_jni_GetDirectBufferAddress(JNIEnv *env, |
| jobject buf)) |
| functionEnter(thr); |
| void* result = UNCHECKED()->GetDirectBufferAddress(env, buf); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jlong, |
| checked_jni_GetDirectBufferCapacity(JNIEnv *env, |
| jobject buf)) |
| functionEnter(thr); |
| jlong result = UNCHECKED()->GetDirectBufferCapacity(env, buf); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobjectRefType, |
| checked_jni_GetObjectRefType(JNIEnv *env, |
| jobject obj)) |
| functionEnter(thr); |
| /* validate the object being passed */ |
| IN_VM( |
| jniCheck::validate_object(thr, obj); |
| ) |
| jobjectRefType result = UNCHECKED()->GetObjectRefType(env, obj); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| |
| JNI_ENTRY_CHECKED(jint, |
| checked_jni_GetVersion(JNIEnv *env)) |
| functionEnter(thr); |
| jint result = UNCHECKED()->GetVersion(env); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| JNI_ENTRY_CHECKED(jobject, |
| checked_jni_GetModule(JNIEnv *env, |
| jclass clazz)) |
| functionEnter(thr); |
| IN_VM( |
| jniCheck::validate_class(thr, clazz, false); |
| ) |
| jobject result = UNCHECKED()->GetModule(env,clazz); |
| functionExit(thr); |
| return result; |
| JNI_END |
| |
| /* |
| * Structure containing all checked jni functions |
| */ |
| struct JNINativeInterface_ checked_jni_NativeInterface = { |
| NULL, |
| NULL, |
| NULL, |
| |
| NULL, |
| |
| checked_jni_GetVersion, |
| |
| checked_jni_DefineClass, |
| checked_jni_FindClass, |
| |
| checked_jni_FromReflectedMethod, |
| checked_jni_FromReflectedField, |
| |
| checked_jni_ToReflectedMethod, |
| |
| checked_jni_GetSuperclass, |
| checked_jni_IsAssignableFrom, |
| |
| checked_jni_ToReflectedField, |
| |
| checked_jni_Throw, |
| checked_jni_ThrowNew, |
| checked_jni_ExceptionOccurred, |
| checked_jni_ExceptionDescribe, |
| checked_jni_ExceptionClear, |
| checked_jni_FatalError, |
| |
| checked_jni_PushLocalFrame, |
| checked_jni_PopLocalFrame, |
| |
| checked_jni_NewGlobalRef, |
| checked_jni_DeleteGlobalRef, |
| checked_jni_DeleteLocalRef, |
| checked_jni_IsSameObject, |
| |
| checked_jni_NewLocalRef, |
| checked_jni_EnsureLocalCapacity, |
| |
| checked_jni_AllocObject, |
| checked_jni_NewObject, |
| checked_jni_NewObjectV, |
| checked_jni_NewObjectA, |
| |
| checked_jni_GetObjectClass, |
| checked_jni_IsInstanceOf, |
| |
| checked_jni_GetMethodID, |
| |
| checked_jni_CallObjectMethod, |
| checked_jni_CallObjectMethodV, |
| checked_jni_CallObjectMethodA, |
| checked_jni_CallBooleanMethod, |
| checked_jni_CallBooleanMethodV, |
| checked_jni_CallBooleanMethodA, |
| checked_jni_CallByteMethod, |
| checked_jni_CallByteMethodV, |
| checked_jni_CallByteMethodA, |
| checked_jni_CallCharMethod, |
| checked_jni_CallCharMethodV, |
| checked_jni_CallCharMethodA, |
| checked_jni_CallShortMethod, |
| checked_jni_CallShortMethodV, |
| checked_jni_CallShortMethodA, |
| checked_jni_CallIntMethod, |
| checked_jni_CallIntMethodV, |
| checked_jni_CallIntMethodA, |
| checked_jni_CallLongMethod, |
| checked_jni_CallLongMethodV, |
| checked_jni_CallLongMethodA, |
| checked_jni_CallFloatMethod, |
| checked_jni_CallFloatMethodV, |
| checked_jni_CallFloatMethodA, |
| checked_jni_CallDoubleMethod, |
| checked_jni_CallDoubleMethodV, |
| checked_jni_CallDoubleMethodA, |
| checked_jni_CallVoidMethod, |
| checked_jni_CallVoidMethodV, |
| checked_jni_CallVoidMethodA, |
| |
| checked_jni_CallNonvirtualObjectMethod, |
| checked_jni_CallNonvirtualObjectMethodV, |
| checked_jni_CallNonvirtualObjectMethodA, |
| checked_jni_CallNonvirtualBooleanMethod, |
| checked_jni_CallNonvirtualBooleanMethodV, |
| checked_jni_CallNonvirtualBooleanMethodA, |
| checked_jni_CallNonvirtualByteMethod, |
| checked_jni_CallNonvirtualByteMethodV, |
| checked_jni_CallNonvirtualByteMethodA, |
| checked_jni_CallNonvirtualCharMethod, |
| checked_jni_CallNonvirtualCharMethodV, |
| checked_jni_CallNonvirtualCharMethodA, |
| checked_jni_CallNonvirtualShortMethod, |
| checked_jni_CallNonvirtualShortMethodV, |
| checked_jni_CallNonvirtualShortMethodA, |
| checked_jni_CallNonvirtualIntMethod, |
| checked_jni_CallNonvirtualIntMethodV, |
| checked_jni_CallNonvirtualIntMethodA, |
| checked_jni_CallNonvirtualLongMethod, |
| checked_jni_CallNonvirtualLongMethodV, |
| checked_jni_CallNonvirtualLongMethodA, |
| checked_jni_CallNonvirtualFloatMethod, |
| checked_jni_CallNonvirtualFloatMethodV, |
| checked_jni_CallNonvirtualFloatMethodA, |
| checked_jni_CallNonvirtualDoubleMethod, |
| checked_jni_CallNonvirtualDoubleMethodV, |
| checked_jni_CallNonvirtualDoubleMethodA, |
| checked_jni_CallNonvirtualVoidMethod, |
| checked_jni_CallNonvirtualVoidMethodV, |
| checked_jni_CallNonvirtualVoidMethodA, |
| |
| checked_jni_GetFieldID, |
| |
| checked_jni_GetObjectField, |
| checked_jni_GetBooleanField, |
| checked_jni_GetByteField, |
| checked_jni_GetCharField, |
| checked_jni_GetShortField, |
| checked_jni_GetIntField, |
| checked_jni_GetLongField, |
| checked_jni_GetFloatField, |
| checked_jni_GetDoubleField, |
| |
| checked_jni_SetObjectField, |
| checked_jni_SetBooleanField, |
| checked_jni_SetByteField, |
| checked_jni_SetCharField, |
| checked_jni_SetShortField, |
| checked_jni_SetIntField, |
| checked_jni_SetLongField, |
| checked_jni_SetFloatField, |
| checked_jni_SetDoubleField, |
| |
| checked_jni_GetStaticMethodID, |
| |
| checked_jni_CallStaticObjectMethod, |
| checked_jni_CallStaticObjectMethodV, |
| checked_jni_CallStaticObjectMethodA, |
| checked_jni_CallStaticBooleanMethod, |
| checked_jni_CallStaticBooleanMethodV, |
| checked_jni_CallStaticBooleanMethodA, |
| checked_jni_CallStaticByteMethod, |
| checked_jni_CallStaticByteMethodV, |
| checked_jni_CallStaticByteMethodA, |
| checked_jni_CallStaticCharMethod, |
| checked_jni_CallStaticCharMethodV, |
| checked_jni_CallStaticCharMethodA, |
| checked_jni_CallStaticShortMethod, |
| checked_jni_CallStaticShortMethodV, |
| checked_jni_CallStaticShortMethodA, |
| checked_jni_CallStaticIntMethod, |
| checked_jni_CallStaticIntMethodV, |
| checked_jni_CallStaticIntMethodA, |
| checked_jni_CallStaticLongMethod, |
| checked_jni_CallStaticLongMethodV, |
| checked_jni_CallStaticLongMethodA, |
| checked_jni_CallStaticFloatMethod, |
| checked_jni_CallStaticFloatMethodV, |
| checked_jni_CallStaticFloatMethodA, |
| checked_jni_CallStaticDoubleMethod, |
| checked_jni_CallStaticDoubleMethodV, |
| checked_jni_CallStaticDoubleMethodA, |
| checked_jni_CallStaticVoidMethod, |
| checked_jni_CallStaticVoidMethodV, |
| checked_jni_CallStaticVoidMethodA, |
| |
| checked_jni_GetStaticFieldID, |
| |
| checked_jni_GetStaticObjectField, |
| checked_jni_GetStaticBooleanField, |
| checked_jni_GetStaticByteField, |
| checked_jni_GetStaticCharField, |
| checked_jni_GetStaticShortField, |
| checked_jni_GetStaticIntField, |
| checked_jni_GetStaticLongField, |
| checked_jni_GetStaticFloatField, |
| checked_jni_GetStaticDoubleField, |
| |
| checked_jni_SetStaticObjectField, |
| checked_jni_SetStaticBooleanField, |
| checked_jni_SetStaticByteField, |
| checked_jni_SetStaticCharField, |
| checked_jni_SetStaticShortField, |
| checked_jni_SetStaticIntField, |
| checked_jni_SetStaticLongField, |
| checked_jni_SetStaticFloatField, |
| checked_jni_SetStaticDoubleField, |
| |
| checked_jni_NewString, |
| checked_jni_GetStringLength, |
| checked_jni_GetStringChars, |
| checked_jni_ReleaseStringChars, |
| |
| checked_jni_NewStringUTF, |
| checked_jni_GetStringUTFLength, |
| checked_jni_GetStringUTFChars, |
| checked_jni_ReleaseStringUTFChars, |
| |
| checked_jni_GetArrayLength, |
| |
| checked_jni_NewObjectArray, |
| checked_jni_GetObjectArrayElement, |
| checked_jni_SetObjectArrayElement, |
| |
| checked_jni_NewBooleanArray, |
| checked_jni_NewByteArray, |
| checked_jni_NewCharArray, |
| checked_jni_NewShortArray, |
| checked_jni_NewIntArray, |
| checked_jni_NewLongArray, |
| checked_jni_NewFloatArray, |
| checked_jni_NewDoubleArray, |
| |
| checked_jni_GetBooleanArrayElements, |
| checked_jni_GetByteArrayElements, |
| checked_jni_GetCharArrayElements, |
| checked_jni_GetShortArrayElements, |
| checked_jni_GetIntArrayElements, |
| checked_jni_GetLongArrayElements, |
| checked_jni_GetFloatArrayElements, |
| checked_jni_GetDoubleArrayElements, |
| |
| checked_jni_ReleaseBooleanArrayElements, |
| checked_jni_ReleaseByteArrayElements, |
| checked_jni_ReleaseCharArrayElements, |
| checked_jni_ReleaseShortArrayElements, |
| checked_jni_ReleaseIntArrayElements, |
| checked_jni_ReleaseLongArrayElements, |
| checked_jni_ReleaseFloatArrayElements, |
| checked_jni_ReleaseDoubleArrayElements, |
| |
| checked_jni_GetBooleanArrayRegion, |
| checked_jni_GetByteArrayRegion, |
| checked_jni_GetCharArrayRegion, |
| checked_jni_GetShortArrayRegion, |
| checked_jni_GetIntArrayRegion, |
| checked_jni_GetLongArrayRegion, |
| checked_jni_GetFloatArrayRegion, |
| checked_jni_GetDoubleArrayRegion, |
| |
| checked_jni_SetBooleanArrayRegion, |
| checked_jni_SetByteArrayRegion, |
| checked_jni_SetCharArrayRegion, |
| checked_jni_SetShortArrayRegion, |
| checked_jni_SetIntArrayRegion, |
| checked_jni_SetLongArrayRegion, |
| checked_jni_SetFloatArrayRegion, |
| checked_jni_SetDoubleArrayRegion, |
| |
| checked_jni_RegisterNatives, |
| checked_jni_UnregisterNatives, |
| |
| checked_jni_MonitorEnter, |
| checked_jni_MonitorExit, |
| |
| checked_jni_GetJavaVM, |
| |
| checked_jni_GetStringRegion, |
| checked_jni_GetStringUTFRegion, |
| |
| checked_jni_GetPrimitiveArrayCritical, |
| checked_jni_ReleasePrimitiveArrayCritical, |
| |
| checked_jni_GetStringCritical, |
| checked_jni_ReleaseStringCritical, |
| |
| checked_jni_NewWeakGlobalRef, |
| checked_jni_DeleteWeakGlobalRef, |
| |
| checked_jni_ExceptionCheck, |
| |
| checked_jni_NewDirectByteBuffer, |
| checked_jni_GetDirectBufferAddress, |
| checked_jni_GetDirectBufferCapacity, |
| |
| // New 1.6 Features |
| |
| checked_jni_GetObjectRefType, |
| |
| // Module Features |
| |
| checked_jni_GetModule |
| }; |
| |
| |
| // Returns the function structure |
| struct JNINativeInterface_* jni_functions_check() { |
| |
| unchecked_jni_NativeInterface = jni_functions_nocheck(); |
| |
| // make sure the last pointer in the checked table is not null, indicating |
| // an addition to the JNINativeInterface_ structure without initializing |
| // it in the checked table. |
| debug_only(int *lastPtr = (int *)((char *)&checked_jni_NativeInterface + \ |
| sizeof(*unchecked_jni_NativeInterface) - sizeof(char *));) |
| assert(*lastPtr != 0, |
| "Mismatched JNINativeInterface tables, check for new entries"); |
| |
| // with -verbose:jni this message will print |
| if (PrintJNIResolving) { |
| tty->print_cr("Checked JNI functions are being used to " \ |
| "validate JNI usage"); |
| } |
| |
| return &checked_jni_NativeInterface; |
| } |