Skip to content

Commit

Permalink
Minimizing allocations in exception processing
Browse files Browse the repository at this point in the history
  • Loading branch information
gershnik committed May 7, 2024
1 parent 2dd1015 commit ce81ce2
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 10 deletions.
21 changes: 11 additions & 10 deletions src/java_exception.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@

using namespace smjni;

static constexpr char g_defaultWhat[] = "smjni::java_exception";
static constexpr char g_defaultWhatPrefix[] = "smjni::java_exception: ";



const char * java_exception::what() const noexcept
{
if (m_what.empty())
Expand All @@ -43,19 +48,15 @@ const char * java_exception::what() const noexcept

std::string java_exception::do_what() const
{
std::string ret = "smjni::java_exception";

JNIEnv * jenv = jni_provider::get_jni();
auto message = java_runtime::object().toString(jenv, m_throwable.c_ptr());
if (!message)
return ret;
jsize len = java_string_get_length(jenv, message);
if (!len)
return ret;
std::vector<jchar> buf(len);
java_string_get_region(jenv, message, 0, len, &buf[0]);
ret += ": ";
utf16_to_utf8(buf.begin(), buf.end(), std::back_inserter(ret));
return g_defaultWhat;
java_string_access messageAccess(jenv, message);
std::string ret;
ret.reserve(std::size(g_defaultWhatPrefix) - 1 + messageAccess.size());
ret = g_defaultWhatPrefix;
utf16_to_utf8(messageAccess.begin(), messageAccess.end(), std::back_inserter(ret));
return ret;
}

Expand Down
21 changes: 21 additions & 0 deletions tests/src/cpp/integration_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,4 +251,25 @@ jByteBuffer JNICALL TestSimpleJNI::doTestDirectBuffer(JNIEnv * env, jclass, jByt
return nullptr;
}

TEST_CASE( "testExceptionFromJava" )
{
JNIEnv * env = jni_provider::get_jni();
CHECK_THROWS_WITH_AS(java_classes::get<TestSimpleJNI>().testExceptionFromJava(env),
"smjni::java_exception: java.lang.RuntimeException: hello world", smjni::java_exception);
}

TEST_CASE( "testExceptionPassthrough" )
{
JNIEnv * env = jni_provider::get_jni();
java_classes::get<TestSimpleJNI>().testExceptionPassthrough(env);
}

void JNICALL TestSimpleJNI::doTestExceptionPassthrough(JNIEnv * env, jclass)
{
NATIVE_PROLOG
java_classes::get<TestSimpleJNI>().testExceptionFromJava(env);
NATIVE_EPILOG
}


TEST_SUITE_END();
19 changes: 19 additions & 0 deletions tests/src/java/smjni/tests/TestSimpleJNI.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,23 @@ private static void testDirectBuffer()
}

private static native ByteBuffer doTestDirectBuffer(ByteBuffer buffer);

@CalledByNative
private static void testExceptionFromJava() {
throw new RuntimeException("hello world");
}

@CalledByNative
private static void testExceptionPassthrough() {
try {
doTestExceptionPassthrough();
fail("exception not thrown");
} catch(RuntimeException ex) {
assertEquals(ex.toString(), "java.lang.RuntimeException: hello world");
} catch(Exception ex) {
fail("exception of wrong type thrown");
}
}

private static native void doTestExceptionPassthrough();
}

0 comments on commit ce81ce2

Please sign in to comment.