From 3368a5eb47ae88fb6db260a916a41eab663cce69 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 1 May 2025 15:04:25 -0600 Subject: [PATCH] JNI: optimize out CallIntMethod/CallBooleanMethod() calls from WolfSSLSession.read(ByteBuffer), improves performance --- native/com_wolfssl_WolfSSLSession.c | 31 +++++------------------- native/com_wolfssl_WolfSSLSession.h | 6 ++--- src/java/com/wolfssl/WolfSSLSession.java | 13 ++++++++-- 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index b7c3019..e3767fa 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -1361,18 +1361,15 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__J_3BIII return size; } -JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuffer_2II - (JNIEnv* jenv, jobject jcl, jlong sslPtr, jobject buf, jint length, jint timeout) +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuffer_2IIZII + (JNIEnv* jenv, jobject jcl, jlong sslPtr, jobject buf, jint position, + jint limit, jboolean hasArray, jint length, jint timeout) { int size = 0; int maxOutputSz; int outSz = length; byte* data = NULL; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; - - jint position; - jint limit; - jboolean hasArray; jbyteArray bufArr = NULL; (void)jcl; @@ -1382,17 +1379,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff } if (length > 0) { - /* Get ByteBuffer position */ - position = (*jenv)->CallIntMethod(jenv, buf, g_bufferPositionMethodId); - if ((*jenv)->ExceptionCheck(jenv)) { - return SSL_FAILURE; - } - - /* Get ByteBuffer limit */ - limit = (*jenv)->CallIntMethod(jenv, buf, g_bufferLimitMethodId); - if ((*jenv)->ExceptionCheck(jenv)) { - return SSL_FAILURE; - } /* Only read up to maximum space we have in this ByteBuffer */ maxOutputSz = (limit - position); @@ -1404,13 +1390,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff return BAD_FUNC_ARG; } - /* Get and call ByteBuffer.hasArray() before calling array() */ - hasArray = (*jenv)->CallBooleanMethod(jenv, buf, - g_bufferHasArrayMethodId); - if ((*jenv)->ExceptionCheck(jenv)) { - return SSL_FAILURE; - } - if (hasArray) { /* Get reference to underlying byte[] from ByteBuffer */ bufArr = (jbyteArray)(*jenv)->CallObjectMethod(jenv, buf, @@ -1460,7 +1439,9 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff } } - /* Update ByteBuffer position() based on bytes written, on success */ + /* Update ByteBuffer position() based on bytes written, on success. + * This seems to be more performant if we do it from JNI rather + * than back in Java after the return of this method. */ if (size > 0) { (*jenv)->CallVoidMethod(jenv, buf, g_bufferSetPositionMethodId, position + size); diff --git a/native/com_wolfssl_WolfSSLSession.h b/native/com_wolfssl_WolfSSLSession.h index d50019d..12a4cd4 100644 --- a/native/com_wolfssl_WolfSSLSession.h +++ b/native/com_wolfssl_WolfSSLSession.h @@ -106,10 +106,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__J_3BIII /* * Class: com_wolfssl_WolfSSLSession * Method: read - * Signature: (JLjava/nio/ByteBuffer;II)I + * Signature: (JLjava/nio/ByteBuffer;IIZII)I */ -JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuffer_2II - (JNIEnv *, jobject, jlong, jobject, jint, jint); +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuffer_2IIZII + (JNIEnv *, jobject, jlong, jobject, jint, jint, jboolean, jint, jint); /* * Class: com_wolfssl_WolfSSLSession diff --git a/src/java/com/wolfssl/WolfSSLSession.java b/src/java/com/wolfssl/WolfSSLSession.java index c20b55e..2b16836 100644 --- a/src/java/com/wolfssl/WolfSSLSession.java +++ b/src/java/com/wolfssl/WolfSSLSession.java @@ -382,7 +382,8 @@ public class WolfSSLSession { int timeout); private native int read(long ssl, byte[] data, int offset, int sz, int timeout); - private native int read(long ssl, ByteBuffer data, int sz, int timeout) + private native int read(long ssl, ByteBuffer data, final int position, + final int limit, boolean hasArray, int sz, int timeout) throws WolfSSLException; private native int pending(long ssl); private native int accept(long ssl, int timeout); @@ -1323,6 +1324,9 @@ public class WolfSSLSession { final int err; final int readSz = sz; final int readTimeout = timeout; + final int bbPosition; + final int bbLimit; + boolean hasArray; long localPtr; confirmObjectIsActive(); @@ -1344,7 +1348,12 @@ public class WolfSSLSession { * could timeout waiting for corresponding write() operation to * occur if needed */ try { - ret = read(localPtr, data, readSz, readTimeout); + bbPosition = data.position(); + bbLimit = data.limit(); + hasArray = data.hasArray(); + + ret = read(localPtr, data, bbPosition, bbLimit, hasArray, + readSz, readTimeout); err = getError(ret); } catch (WolfSSLException e) { /* JNI code may throw WolfSSLException on JNI specific errors */