From 3e7187686b5be24a11d10698edb79aa796572afd Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Thu, 2 Dec 2021 09:40:16 -0600 Subject: [PATCH] external: Update jnipp --- src/external/jnipp/.editorconfig | 5 ++ src/external/jnipp/jnipp.cpp | 91 ++++++++++++++++++++++++++++++- src/external/jnipp/jnipp.h | 22 +++++++- src/external/jnipp/makefile | 2 +- src/external/jnipp/tests/main.cpp | 10 ++++ 5 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 src/external/jnipp/.editorconfig diff --git a/src/external/jnipp/.editorconfig b/src/external/jnipp/.editorconfig new file mode 100644 index 000000000..b532cc51a --- /dev/null +++ b/src/external/jnipp/.editorconfig @@ -0,0 +1,5 @@ + +[.h,.cpp] +indent_size = 4 +indent_style = space +trim_trailing_whitespace = true diff --git a/src/external/jnipp/jnipp.cpp b/src/external/jnipp/jnipp.cpp index a250b76cd..852ce39bb 100644 --- a/src/external/jnipp/jnipp.cpp +++ b/src/external/jnipp/jnipp.cpp @@ -6,6 +6,8 @@ #else // UNIX Dependencies # include +# include +# include #endif // External Dependencies @@ -24,6 +26,10 @@ namespace jni static std::atomic_bool isVm(false); static JavaVM* javaVm = nullptr; + static bool isAttached(JavaVM *vm) { + JNIEnv *env = nullptr; + return vm->GetEnv((void **)&env, JNI_VERSION_1_2) == JNI_OK; + } /** Maintains the lifecycle of a JNIEnv. */ @@ -57,7 +63,7 @@ namespace jni if (vm == nullptr) throw InitializationException("JNI not initialized"); - if (vm->GetEnv((void**)&_env, JNI_VERSION_1_2) != JNI_OK) + if (!isAttached(vm)) { #ifdef __ANDROID__ if (vm->AttachCurrentThread(&_env, nullptr) != 0) @@ -150,8 +156,17 @@ namespace jni { static thread_local ScopedEnv env; + if (env.get() != nullptr && !isAttached(javaVm)) + { + // we got detached, so clear it. + // will be re-populated from static javaVm below. + env = ScopedEnv{}; + } + if (env.get() == nullptr) + { env.init(javaVm); + } return env.get(); } @@ -1270,7 +1285,57 @@ namespace jni typedef jint (JNICALL *CreateVm_t)(JavaVM**, void**, void*); +#ifndef _WIN32 + static bool fileExists(const std::string& filePath) + { + return access(filePath.c_str(), F_OK) != -1; + } + + template + static ssize_t readlink_safe(const char *pathname, char (&output)[N]) { + auto len = readlink(pathname, output, N - 1); + if (len > 0) { + output[len] = '\0'; + } + return len; + } + static std::pair + readlink_as_string(const char *pathname) { + char buf[2048] = {}; + auto len = readlink_safe(pathname, buf); + if (len <= 0) { + return {len, {}}; + } + return {len, std::string{buf, static_cast(len)}}; + } + static std::string readlink_deep(const char *pathname) { + std::string prev{pathname}; + ssize_t len = 0; + std::string next; + while (true) { + std::tie(len, next) = readlink_as_string(prev.c_str()); + if (!next.empty()) { + prev = next; + } else { + return prev; + } + } + } + + static std::string drop_path_components(const std::string & path, size_t num_components) { + size_t pos = std::string::npos; + size_t slash_pos = std::string::npos; + for (size_t i = 0; i < num_components; ++i) { + slash_pos = path.find_last_of('/', pos); + if (slash_pos == std::string::npos || slash_pos == 0) { + return {}; + } + pos = slash_pos - 1; + } + return std::string{path.c_str(), slash_pos}; + } +#endif static std::string detectJvmPath() { std::string result; @@ -1321,7 +1386,7 @@ namespace jni javaHome + "\\bin\\server\\jvm.dll" }; - for (auto i : options) + for (auto const& i : options) if (fileExists(i)) return i; } @@ -1338,6 +1403,28 @@ namespace jni #endif result = libJvmPath; } else { + std::string path = readlink_deep("/usr/bin/java"); + if (!path.empty()) { + // drop bin and java + auto javaHome = drop_path_components(path, 2); + if (!javaHome.empty()) { + std::string options[] = { + javaHome + "/jre/lib/amd64/server/libjvm.so", + javaHome + "/jre/lib/amd64/client/libjvm.so", + javaHome + "/jre/lib/server/libjvm.so", + javaHome + "/jre/lib/client/libjvm.so", + javaHome + "/lib/server/libjvm.so", + javaHome + "/lib/client/libjvm.so", + }; + + for (auto const &i : options) { + fprintf(stderr, "trying %s\n", i.c_str()); + if (fileExists(i)) { + return i; + } + } + } + } // Best guess so far. result = "/usr/lib/jvm/default-java/jre/lib/amd64/server/libjvm.so"; } diff --git a/src/external/jnipp/jnipp.h b/src/external/jnipp/jnipp.h index 70515c979..017bdd923 100644 --- a/src/external/jnipp/jnipp.h +++ b/src/external/jnipp/jnipp.h @@ -175,10 +175,30 @@ namespace jni value_t values[sizeof...(TArgs)]; }; + /* specialization for empty array - no args. Avoids "empty array" warning. */ + template <> + class ArgArray<> + { + public: + ArgArray() { + std::memset(this, 0, sizeof(ArgArray<>)); + } + + ~ArgArray() { + } + + value_t values[1]; + }; long getArrayLength(jarray array); + /** + * @brief Used as a tag type for dispatching internally based on return type. + * + * @tparam T The type to wrap. + */ template - struct ReturnTypeWrapper{ + struct ReturnTypeWrapper + { using type = T; }; } diff --git a/src/external/jnipp/makefile b/src/external/jnipp/makefile index 8c069e819..f751afd74 100644 --- a/src/external/jnipp/makefile +++ b/src/external/jnipp/makefile @@ -15,7 +15,7 @@ endif JAVA_HOME ?= /usr/lib/jvm/default-java -CXXFLAGS=-I. -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(OS_NAME) -ldl -std=c++11 +CXXFLAGS=-I. -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(OS_NAME) -ldl -std=c++11 -Wall -g SRC=jnipp.o main.o VPATH=tests diff --git a/src/external/jnipp/tests/main.cpp b/src/external/jnipp/tests/main.cpp index 96de84296..d40355922 100644 --- a/src/external/jnipp/tests/main.cpp +++ b/src/external/jnipp/tests/main.cpp @@ -249,6 +249,15 @@ TEST(Object_moveAssignmentOperator) ASSERT(b.isNull()); } +TEST(Object_nullary_construct_from_signature) +{ + jni::Class String("java/lang/String"); + jni::method_t init = String.getMethod("", "()V"); + jni::Object i = String.newInstance(init); + ASSERT(!i.isNull()); + jni::internal::ArgArray<> a; +} + TEST(Object_call) { jni::Class Integer("java/lang/Integer"); @@ -575,6 +584,7 @@ int main() // jni::Object Tests RUN_TEST(Object_defaultConstructor_isNull); + RUN_TEST(Object_nullary_construct_from_signature); RUN_TEST(Object_copyConstructorIsSameObject); RUN_TEST(Object_moveConstructor); RUN_TEST(Object_copyAssignmentOperator); -- 2.51.2