1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2018, Google and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 #include <stdlib.h> 26 27 #include "ExceptionCheckingJniEnv.hpp" 28 29 namespace { 30 31 template<class T = void*> 32 class JNIVerifier { 33 public: 34 JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_msg) 35 : _env(env), _base_msg(base_msg), _return_error(NULL) { 36 } 37 38 ~JNIVerifier() { 39 JNIEnv* jni_env = _env->GetJNIEnv(); 40 if (jni_env->ExceptionCheck()) { 41 _env->HandleError(_base_msg); 42 return; 43 } 44 45 if (_return_error != NULL) { 46 ProcessReturnError(); 47 } 48 } 49 50 void ProcessReturnError() { 51 int len = snprintf(NULL, 0, "%s : %s", _base_msg, _return_error) + 1; 52 53 if (len <= 0) { 54 _env->HandleError(_return_error); 55 return; 56 } 57 58 char* full_message = (char*) malloc(len); 59 if (full_message == NULL) { 60 _env->HandleError(_return_error); 61 return; 62 } 63 64 snprintf(full_message, len, "%s : %s", _base_msg, _return_error); 65 66 _env->HandleError(full_message); 67 free(full_message); 68 } 69 70 T ResultNotNull(T ptr) { 71 if (ptr == NULL) { 72 _return_error = "Return is NULL"; 73 } 74 return ptr; 75 } 76 77 private: 78 ExceptionCheckingJniEnv* _env; 79 const char* const _base_msg; 80 const char* _return_error; 81 }; 82 83 } 84 85 jclass ExceptionCheckingJniEnv::GetObjectClass(jobject obj) { 86 JNIVerifier<jclass> marker(this, "GetObjectClass"); 87 return marker.ResultNotNull(_jni_env->GetObjectClass(obj)); 88 } 89 90 jfieldID ExceptionCheckingJniEnv::GetFieldID(jclass klass, const char *name, const char* type) { 91 JNIVerifier<jfieldID> marker(this, "GetFieldID"); 92 return marker.ResultNotNull(_jni_env->GetFieldID(klass, name, type)); 93 } 94 95 jobject ExceptionCheckingJniEnv::GetObjectField(jobject obj, jfieldID field) { 96 JNIVerifier<jobject> marker(this, "GetObjectField"); 97 return marker.ResultNotNull(_jni_env->GetObjectField(obj, field)); 98 } 99 100 void ExceptionCheckingJniEnv::SetObjectField(jobject obj, jfieldID field, jobject value) { 101 JNIVerifier<> marker(this, "SetObjectField"); 102 _jni_env->SetObjectField(obj, field, value); 103 } 104 105 jobject ExceptionCheckingJniEnv::NewGlobalRef(jobject obj) { 106 JNIVerifier<jobject> marker(this, "NewGlobalRef"); 107 return marker.ResultNotNull(_jni_env->NewGlobalRef(obj)); 108 } 109 110 void ExceptionCheckingJniEnv::DeleteGlobalRef(jobject obj) { 111 JNIVerifier<> marker(this, "DeleteGlobalRef"); 112 _jni_env->DeleteGlobalRef(obj); 113 } 114 115 jobject ExceptionCheckingJniEnv::NewLocalRef(jobject obj) { 116 JNIVerifier<jobject> marker(this, "NewLocalRef"); 117 return marker.ResultNotNull(_jni_env->NewLocalRef(obj)); 118 } 119 120 void ExceptionCheckingJniEnv::DeleteLocalRef(jobject obj) { 121 JNIVerifier<> marker(this, "DeleteLocalRef"); 122 _jni_env->DeleteLocalRef(obj); 123 } 124 125 jweak ExceptionCheckingJniEnv::NewWeakGlobalRef(jobject obj) { 126 JNIVerifier<jweak> marker(this, "NewWeakGlobalRef"); 127 return marker.ResultNotNull(_jni_env->NewWeakGlobalRef(obj)); 128 } 129 130 void ExceptionCheckingJniEnv::DeleteWeakGlobalRef(jweak weak_ref) { 131 JNIVerifier<> marker(this, "DeleteWeakGlobalRef"); 132 _jni_env->DeleteWeakGlobalRef(weak_ref); 133 } 134 135 jsize ExceptionCheckingJniEnv::GetArrayLength(jarray array) { 136 JNIVerifier<> marker(this, "GetArrayLength"); 137 return _jni_env->GetArrayLength(array); 138 } 139 140 jsize ExceptionCheckingJniEnv::GetStringLength(jstring str) { 141 JNIVerifier<> marker(this, "GetStringLength"); 142 return _jni_env->GetStringLength(str); 143 } 144 145 void* ExceptionCheckingJniEnv::GetPrimitiveArrayCritical(jarray array, jboolean* isCopy) { 146 JNIVerifier<> marker(this, "GetPrimitiveArrayCritical"); 147 return marker.ResultNotNull(_jni_env->GetPrimitiveArrayCritical(array, isCopy)); 148 } 149 150 void ExceptionCheckingJniEnv::ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode) { 151 JNIVerifier<> marker(this, "ReleasePrimitiveArrayCritical"); 152 _jni_env->ReleasePrimitiveArrayCritical(array, carray, mode); 153 } 154 155 const jchar* ExceptionCheckingJniEnv::GetStringCritical(jstring str, jboolean* isCopy) { 156 JNIVerifier<const jchar*> marker(this, "GetPrimitiveArrayCritical"); 157 return marker.ResultNotNull(_jni_env->GetStringCritical(str, isCopy)); 158 } 159 160 void ExceptionCheckingJniEnv::ReleaseStringCritical(jstring str, const jchar* carray) { 161 JNIVerifier<> marker(this, "ReleaseStringCritical"); 162 _jni_env->ReleaseStringCritical(str, carray); 163 }