JSSE: cache jmethodIDs used in native I/O callbacks globally, improves performance

pull/257/head
Chris Conlon 2025-04-14 16:43:20 -06:00
parent d95297f12c
commit 767a289113
4 changed files with 153 additions and 161 deletions

View File

@ -53,6 +53,16 @@ JavaVM* g_vm;
/* global object refs for logging callbacks */ /* global object refs for logging callbacks */
static jobject g_loggingCbIfaceObj; static jobject g_loggingCbIfaceObj;
/* global method IDs we can cache for performance */
jmethodID g_sslIORecvMethodId = NULL;
jmethodID g_sslIOSendMethodId = NULL;
jmethodID g_bufferPositionMethodId = NULL;
jmethodID g_bufferLimitMethodId = NULL;
jmethodID g_bufferHasArrayMethodId = NULL;
jmethodID g_bufferArrayMethodId = NULL;
jmethodID g_bufferSetPositionMethodId = NULL;
jmethodID g_verifyCallbackMethodId = NULL;
#ifdef HAVE_FIPS #ifdef HAVE_FIPS
/* global object ref for FIPS error callback */ /* global object ref for FIPS error callback */
static jobject g_fipsCbIfaceObj; static jobject g_fipsCbIfaceObj;
@ -61,16 +71,116 @@ static jobject g_fipsCbIfaceObj;
/* custom native fn prototypes */ /* custom native fn prototypes */
void NativeLoggingCallback(const int logLevel, const char *const logMessage); void NativeLoggingCallback(const int logLevel, const char *const logMessage);
/* called when native library is loaded */ /* Called when native library is loaded.
* We also cache global jmethodIDs here for performance. */
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{ {
JNIEnv* env = NULL;
jclass sslClass = NULL;
jclass byteBufferClass = NULL;
jclass verifyClass = NULL;
(void)reserved; (void)reserved;
/* store JavaVM */ /* store JavaVM */
g_vm = vm; g_vm = vm;
/* get JNIEnv from JavaVM */
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) {
printf("Unable to get JNIEnv from JavaVM in JNI_OnLoad()\n");
return JNI_ERR;
}
/* Cache the method ID for IO send and recv callbacks */
sslClass = (*env)->FindClass(env, "com/wolfssl/WolfSSLSession");
if (sslClass == NULL) {
return JNI_ERR;
}
g_sslIORecvMethodId = (*env)->GetMethodID(env, sslClass,
"internalIOSSLRecvCallback",
"(Lcom/wolfssl/WolfSSLSession;[BI)I");
g_sslIOSendMethodId = (*env)->GetMethodID(env, sslClass,
"internalIOSSLSendCallback",
"(Lcom/wolfssl/WolfSSLSession;[BI)I");
/* Cache ByteBuffer method IDs */
byteBufferClass = (*env)->FindClass(env, "java/nio/ByteBuffer");
if (byteBufferClass == NULL) {
return JNI_ERR;
}
g_bufferPositionMethodId = (*env)->GetMethodID(env, byteBufferClass,
"position", "()I");
if (g_bufferPositionMethodId == NULL) {
return JNI_ERR;
}
g_bufferLimitMethodId = (*env)->GetMethodID(env, byteBufferClass,
"limit", "()I");
if (g_bufferLimitMethodId == NULL) {
return JNI_ERR;
}
g_bufferHasArrayMethodId = (*env)->GetMethodID(env, byteBufferClass,
"hasArray", "()Z");
if (g_bufferHasArrayMethodId == NULL) {
return JNI_ERR;
}
g_bufferArrayMethodId = (*env)->GetMethodID(env, byteBufferClass,
"array", "()[B");
if (g_bufferArrayMethodId == NULL) {
return JNI_ERR;
}
g_bufferSetPositionMethodId = (*env)->GetMethodID(env, byteBufferClass,
"position", "(I)Ljava/nio/Buffer;");
if (g_bufferSetPositionMethodId == NULL) {
return JNI_ERR;
}
/* Cache verify callback method ID */
verifyClass = (*env)->FindClass(env, "com/wolfssl/WolfSSLVerifyCallback");
if (verifyClass == NULL) {
return JNI_ERR;
}
g_verifyCallbackMethodId = (*env)->GetMethodID(env, verifyClass,
"verifyCallback", "(IJ)I");
if (g_verifyCallbackMethodId == NULL) {
return JNI_ERR;
}
/* Clean up local reference to class, not needed */
(*env)->DeleteLocalRef(env, sslClass);
(*env)->DeleteLocalRef(env, byteBufferClass);
(*env)->DeleteLocalRef(env, verifyClass);
return JNI_VERSION_1_6; return JNI_VERSION_1_6;
} }
/* Called when native library is unloaded.
* We clear cached method IDs here. */
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved)
{
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) {
return;
}
/* Clear cached method ID */
g_sslIORecvMethodId = NULL;
g_sslIOSendMethodId = NULL;
g_bufferPositionMethodId = NULL;
g_bufferLimitMethodId = NULL;
g_bufferHasArrayMethodId = NULL;
g_bufferArrayMethodId = NULL;
g_bufferSetPositionMethodId = NULL;
g_verifyCallbackMethodId = NULL;
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_init JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_init
(JNIEnv* jenv, jobject jcl) (JNIEnv* jenv, jobject jcl)
{ {

View File

@ -1028,7 +1028,6 @@ int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
jobject ctxRef; /* WolfSSLContext object */ jobject ctxRef; /* WolfSSLContext object */
jclass innerCtxClass; /* WolfSSLContext class */ jclass innerCtxClass; /* WolfSSLContext class */
jmethodID recvCbMethodId; /* internalIORecvCallback ID */
jbyteArray inData; jbyteArray inData;
if (!g_vm || !ssl || !buf || !ctx) { if (!g_vm || !ssl || !buf || !ctx) {
@ -1140,18 +1139,10 @@ int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
return WOLFSSL_CBIO_ERR_GENERAL; return WOLFSSL_CBIO_ERR_GENERAL;
} }
/* call internal I/O recv callback */ /* make sure cached recv callback method ID is not null */
recvCbMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass, if (!g_sslIORecvMethodId) {
"internalIORecvCallback",
"(Lcom/wolfssl/WolfSSLSession;[BI)I");
if (!recvCbMethodId) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass, (*jenv)->ThrowNew(jenv, excClass,
"Error getting internalIORecvCallback method from JNI"); "Cached recv callback method ID is null in NativeIORecvCb");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) if (needsDetach)
(*g_vm)->DetachCurrentThread(g_vm); (*g_vm)->DetachCurrentThread(g_vm);
return WOLFSSL_CBIO_ERR_GENERAL; return WOLFSSL_CBIO_ERR_GENERAL;
@ -1161,7 +1152,7 @@ int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
inData = (*jenv)->NewByteArray(jenv, sz); inData = (*jenv)->NewByteArray(jenv, sz);
if (!inData) { if (!inData) {
(*jenv)->ThrowNew(jenv, excClass, (*jenv)->ThrowNew(jenv, excClass,
"Error getting internalIORecvCallback method from JNI"); "Error creating jbyteArray in NativeIORecvCb");
(*jenv)->DeleteLocalRef(jenv, ctxRef); (*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) if (needsDetach)
(*g_vm)->DetachCurrentThread(g_vm); (*g_vm)->DetachCurrentThread(g_vm);
@ -1170,7 +1161,7 @@ int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
/* call Java send callback, ignore native ctx since Java /* call Java send callback, ignore native ctx since Java
* handles it */ * handles it */
retval = (*jenv)->CallIntMethod(jenv, ctxRef, recvCbMethodId, retval = (*jenv)->CallIntMethod(jenv, ctxRef, g_sslIORecvMethodId,
(jobject)(*g_cachedSSLObj), (jobject)(*g_cachedSSLObj),
inData, (jint)sz); inData, (jint)sz);

View File

@ -103,8 +103,6 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store)
jint vmret = 0; jint vmret = 0;
jint retval = -1; jint retval = -1;
jclass excClass; jclass excClass;
jclass verifyClass = NULL;
jmethodID verifyMethod;
jobjectRefType refcheck; jobjectRefType refcheck;
SSLAppData* appData; /* WOLFSSL app data, stored verify cb obj */ SSLAppData* appData; /* WOLFSSL app data, stored verify cb obj */
jobject* g_verifySSLCbIfaceObj; /* Global jobject, stored in app data */ jobject* g_verifySSLCbIfaceObj; /* Global jobject, stored in app data */
@ -156,34 +154,20 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store)
refcheck = (*jenv)->GetObjectRefType(jenv, *g_verifySSLCbIfaceObj); refcheck = (*jenv)->GetObjectRefType(jenv, *g_verifySSLCbIfaceObj);
if (refcheck == 2) { if (refcheck == 2) {
/* lookup WolfSSLVerifyCallback class from global object ref */ if (!g_verifyCallbackMethodId) {
verifyClass = (*jenv)->GetObjectClass(jenv, *g_verifySSLCbIfaceObj);
if (!verifyClass) {
if ((*jenv)->ExceptionOccurred(jenv)) { if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv); (*jenv)->ExceptionClear(jenv);
} }
(*jenv)->ThrowNew(jenv, excClass, (*jenv)->ThrowNew(jenv, excClass,
"Can't get native WolfSSLVerifyCallback class reference"); "verifyCallback method ID is null in NativeSSLVerifyCallback");
return -107; return -107;
} }
verifyMethod = (*jenv)->GetMethodID(jenv, verifyClass,
"verifyCallback", "(IJ)I");
if (verifyMethod == 0) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Error getting verifyCallback method from JNI");
return -108;
}
retval = (*jenv)->CallIntMethod(jenv, *g_verifySSLCbIfaceObj, retval = (*jenv)->CallIntMethod(jenv, *g_verifySSLCbIfaceObj,
verifyMethod, preverify_ok, (jlong)(uintptr_t)store); g_verifyCallbackMethodId, preverify_ok,
(jlong)(uintptr_t)store);
if ((*jenv)->ExceptionOccurred(jenv)) { if ((*jenv)->ExceptionOccurred(jenv)) {
/* exception occurred on the Java side during method call */ /* exception occurred on the Java side during method call */
@ -1415,14 +1399,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff
int outSz = length; int outSz = length;
byte* data = NULL; byte* data = NULL;
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
jclass excClass; jclass excClass;
jclass buffClass;
jmethodID positionMeth;
jmethodID limitMeth;
jmethodID hasArrayMeth;
jmethodID arrayMeth;
jmethodID setPositionMeth;
jint position; jint position;
jint limit; jint limit;
@ -1444,51 +1421,15 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff
return -1; return -1;
} }
/* Get ByteBuffer class */
buffClass = (*jenv)->GetObjectClass(jenv, buf);
if (buffClass == NULL) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to find ByteBuffer class in native read()");
return -1;
}
/* Get ByteBuffer position */ /* Get ByteBuffer position */
positionMeth = (*jenv)->GetMethodID(jenv, buffClass, "position", "()I"); position = (*jenv)->CallIntMethod(jenv, buf, g_bufferPositionMethodId);
if (positionMeth == NULL) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Failed to find ByteBuffer position() method in native read()");
return -1;
}
position = (*jenv)->CallIntMethod(jenv, buf, positionMeth);
/* Get ByteBuffer limit */ /* Get ByteBuffer limit */
limitMeth = (*jenv)->GetMethodID(jenv, buffClass, "limit", "()I"); limit = (*jenv)->CallIntMethod(jenv, buf, g_bufferLimitMethodId);
if (limitMeth == NULL) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Failed to find ByteBuffer limit() method in native read()");
return -1;
}
limit = (*jenv)->CallIntMethod(jenv, buf, limitMeth);
/* Get and call ByteBuffer.hasArray() before calling array() */ /* Get and call ByteBuffer.hasArray() before calling array() */
hasArrayMeth = (*jenv)->GetMethodID(jenv, buffClass, "hasArray", "()Z"); hasArray = (*jenv)->CallBooleanMethod(jenv, buf,
if (hasArrayMeth == NULL) { g_bufferHasArrayMethodId);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Failed to find ByteBuffer hasArray() method in native read()");
return -1;
}
/* Only read up to maximum space we have in this ByteBuffer */ /* Only read up to maximum space we have in this ByteBuffer */
maxOutputSz = (limit - position); maxOutputSz = (limit - position);
@ -1496,21 +1437,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff
outSz = maxOutputSz; outSz = maxOutputSz;
} }
hasArray = (*jenv)->CallBooleanMethod(jenv, buf, hasArrayMeth);
if (hasArray) { if (hasArray) {
/* Get reference to underlying byte[] from ByteBuffer */ /* Get reference to underlying byte[] from ByteBuffer */
arrayMeth = (*jenv)->GetMethodID(jenv, buffClass, "array", "()[B"); bufArr = (jbyteArray)(*jenv)->CallObjectMethod(jenv, buf,
if (arrayMeth == NULL) { g_bufferArrayMethodId);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Failed to find ByteBuffer array() method in native read()");
return -1;
}
bufArr = (jbyteArray)(*jenv)->CallObjectMethod(jenv, buf, arrayMeth);
/* Get array elements */ /* Get array elements */
data = (byte *)(*jenv)->GetByteArrayElements(jenv, bufArr, NULL); data = (byte *)(*jenv)->GetByteArrayElements(jenv, bufArr, NULL);
@ -1518,7 +1448,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff
(*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv); (*jenv)->ExceptionClear(jenv);
(*jenv)->ThrowNew(jenv, excClass, (*jenv)->ThrowNew(jenv, excClass,
"Exception when calling ByteBuffer.array() in native read()"); "Exception when calling ByteBuffer.array() in native read()");
return -1; return -1;
} }
} }
@ -1526,24 +1456,24 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff
data = (byte *)(*jenv)->GetDirectBufferAddress(jenv, buf); data = (byte *)(*jenv)->GetDirectBufferAddress(jenv, buf);
if (data == NULL) { if (data == NULL) {
(*jenv)->ThrowNew(jenv, excClass, (*jenv)->ThrowNew(jenv, excClass,
"Failed to get DirectBuffer address in native read()"); "Failed to get DirectBuffer address in native read()");
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
} }
if (data != NULL) { if (data != NULL) {
size = SSLReadNonblockingWithSelectPoll(ssl, data + position, size = SSLReadNonblockingWithSelectPoll(ssl, data + position,
maxOutputSz, (int)timeout); maxOutputSz, (int)timeout);
/* Relase array elements */ /* Relase array elements */
if (hasArray) { if (hasArray) {
if (size < 0) { if (size < 0) {
(*jenv)->ReleaseByteArrayElements(jenv, bufArr, (jbyte *)data, (*jenv)->ReleaseByteArrayElements(jenv, bufArr,
JNI_ABORT); (jbyte *)data, JNI_ABORT);
} }
else { else {
(*jenv)->ReleaseByteArrayElements(jenv, bufArr, (*jenv)->ReleaseByteArrayElements(jenv, bufArr,
(jbyte *)data, 0); (jbyte *)data, 0);
} }
} }
@ -1551,22 +1481,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff
if (size > 0) { if (size > 0) {
/* Update ByteBuffer position() based on bytes written */ /* Update ByteBuffer position() based on bytes written */
setPositionMeth = (*jenv)->GetMethodID(jenv, buffClass, (*jenv)->CallVoidMethod(jenv, buf, g_bufferSetPositionMethodId,
"position", "(I)Ljava/nio/Buffer;"); position + size);
if (setPositionMeth == NULL) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Failed to set ByteBuffer position() from "
"native read()");
size = -1;
}
else {
(*jenv)->CallVoidMethod(jenv, buf, setPositionMeth,
position + size);
}
} }
} }
} }
@ -6143,8 +6059,6 @@ int NativeSSLIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
int needsDetach = 0; /* Should we explicitly detach? */ int needsDetach = 0; /* Should we explicitly detach? */
jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jobject* g_cachedSSLObj; /* WolfSSLSession cached object */
jclass sslClass; /* WolfSSLSession class */
jmethodID recvCbMethodId; /* internalIORecvCallback ID */
jbyteArray inData; jbyteArray inData;
if (!g_vm || !ssl || !buf || !ctx) { if (!g_vm || !ssl || !buf || !ctx) {
@ -6189,28 +6103,9 @@ int NativeSSLIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
return 0; return 0;
} }
/* lookup WolfSSLSession class from object */ if (!g_sslIORecvMethodId) {
sslClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
if (!sslClass) {
(*jenv)->ThrowNew(jenv, excClass, (*jenv)->ThrowNew(jenv, excClass,
"Can't get native WolfSSLSession class reference in " "Cached recv callback method ID is null in internalIORecvCallback");
"NativeSSLIORecvCb");
if (needsDetach)
(*g_vm)->DetachCurrentThread(g_vm);
return WOLFSSL_CBIO_ERR_GENERAL;
}
/* call internal I/O recv callback */
recvCbMethodId = (*jenv)->GetMethodID(jenv, sslClass,
"internalIOSSLRecvCallback",
"(Lcom/wolfssl/WolfSSLSession;[BI)I");
if (!recvCbMethodId) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Error getting internalIORecvCallback method from JNI");
if (needsDetach) if (needsDetach)
(*g_vm)->DetachCurrentThread(g_vm); (*g_vm)->DetachCurrentThread(g_vm);
return WOLFSSL_CBIO_ERR_GENERAL; return WOLFSSL_CBIO_ERR_GENERAL;
@ -6229,7 +6124,7 @@ int NativeSSLIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
/* call Java send callback, ignore native ctx since Java /* call Java send callback, ignore native ctx since Java
* handles it */ * handles it */
retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj), retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj),
recvCbMethodId, (jobject)(*g_cachedSSLObj), inData, (jint)sz); g_sslIORecvMethodId, (jobject)(*g_cachedSSLObj), inData, (jint)sz);
if ((*jenv)->ExceptionOccurred(jenv)) { if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionDescribe(jenv);
@ -6285,8 +6180,6 @@ int NativeSSLIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
int needsDetach = 0; /* Should we explicitly detach? */ int needsDetach = 0; /* Should we explicitly detach? */
jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ jobject* g_cachedSSLObj; /* WolfSSLSession cached object */
jclass sslClass; /* WolfSSLSession class */
jmethodID sendCbMethodId; /* internalIOSendCallback ID */
jbyteArray outData; /* jbyteArray for data to send */ jbyteArray outData; /* jbyteArray for data to send */
if (!g_vm || !ssl || !buf || !ctx) { if (!g_vm || !ssl || !buf || !ctx) {
@ -6331,27 +6224,14 @@ int NativeSSLIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
return 0; return 0;
} }
/* lookup WolfSSLSession class from object */
sslClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
if (!sslClass) {
(*jenv)->ThrowNew(jenv, excClass,
"Can't get native WolfSSLSession class reference");
if (needsDetach)
(*g_vm)->DetachCurrentThread(g_vm);
return WOLFSSL_CBIO_ERR_GENERAL;
}
/* call internal I/O send callback */ /* call internal I/O send callback */
sendCbMethodId = (*jenv)->GetMethodID(jenv, sslClass, if (!g_sslIOSendMethodId) {
"internalIOSSLSendCallback",
"(Lcom/wolfssl/WolfSSLSession;[BI)I");
if (!sendCbMethodId) {
if ((*jenv)->ExceptionOccurred(jenv)) { if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv); (*jenv)->ExceptionClear(jenv);
} }
(*jenv)->ThrowNew(jenv, excClass, (*jenv)->ThrowNew(jenv, excClass,
"Error getting internalIOSendCallback method from JNI"); "internalIOSendCallback method ID is null in internalIOSendCb");
if (needsDetach) if (needsDetach)
(*g_vm)->DetachCurrentThread(g_vm); (*g_vm)->DetachCurrentThread(g_vm);
return WOLFSSL_CBIO_ERR_GENERAL; return WOLFSSL_CBIO_ERR_GENERAL;
@ -6382,7 +6262,7 @@ int NativeSSLIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
/* call Java send callback, ignore native ctx since Java /* call Java send callback, ignore native ctx since Java
* handles it */ * handles it */
retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj), retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj),
sendCbMethodId, (jobject)(*g_cachedSSLObj), outData, (jint)sz); g_sslIOSendMethodId, (jobject)(*g_cachedSSLObj), outData, (jint)sz);
if ((*jenv)->ExceptionOccurred(jenv)) { if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionDescribe(jenv);

View File

@ -25,7 +25,19 @@
#define _Included_com_wolfssl_globals #define _Included_com_wolfssl_globals
/* global JavaVM reference for JNIEnv lookup */ /* global JavaVM reference for JNIEnv lookup */
extern JavaVM* g_vm; extern JavaVM* g_vm;
/* Cache static jmethodIDs for performance, since they are guaranteed to be the
* same across all threads once cached. Initialized in JNI_OnLoad() and freed in
* JNI_OnUnload(). */
extern jmethodID g_sslIORecvMethodId; /* WolfSSLSession.internalIOSSLRecvCallback */
extern jmethodID g_sslIOSendMethodId; /* WolfSSLSession.internalIOSSLSendCallback */
extern jmethodID g_bufferPositionMethodId; /* ByteBuffer.position() */
extern jmethodID g_bufferLimitMethodId; /* ByteBuffer.limit() */
extern jmethodID g_bufferHasArrayMethodId; /* ByteBuffer.hasArray() */
extern jmethodID g_bufferArrayMethodId; /* ByteBuffer.array() */
extern jmethodID g_bufferSetPositionMethodId; /* ByteBuffer.position(int) */
extern jmethodID g_verifyCallbackMethodId; /* WolfSSLVerifyCallback.verifyCallback */
/* struct to hold I/O class, object refs */ /* struct to hold I/O class, object refs */
typedef struct { typedef struct {
@ -39,4 +51,3 @@ unsigned int NativePskServerCb(WOLFSSL* ssl, const char* identity,
unsigned char* key, unsigned int max_key_len); unsigned char* key, unsigned int max_key_len);
#endif #endif