From baba2c213770972e79be6be4902716278f351fb4 Mon Sep 17 00:00:00 2001 From: James Le Cuirot Date: Wed, 24 Aug 2016 23:32:13 +0100 Subject: [PATCH 1/2] Allow libjvm.so to be dlopen'd with --with-jvm-lib=dlopen Having to set LD_LIBRARY_PATH is a pain and relying on the rpath can be problematic when libjvm.so lives in a versioned directory. Some distributions even allow per-user JVM selection so checking the value of JAVA_HOME at runtime allows this choice to be respected. libjvm.so's location is hard to predict (amd64 vs i386, jre or not?) so ${JAVA_HOME}/bin/java -XshowSettings is executed to find its location. If JAVA_HOME is not set then java is executed from the PATH instead. --- gdal/configure | 11 +++++- gdal/configure.in | 7 +++- gdal/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp | 57 +++++++++++++++++++++++++++-- gdal/port/cpl_config.h.in | 3 ++ 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/configure b/configure index 75e4e279de..acdfa439de 100755 --- a/configure +++ b/configure @@ -1753,7 +1753,7 @@ Optional Packages: --with-python=ARG Enable python bindings (ARG=yes, no, or path to python binary) --with-java Include Java support (ARG=yes, no or JDK home path) [default=no] --with-mdb Include MDB driver - --with-jvm-lib=ARG ARG points to Java libjvm path + --with-jvm-lib=ARG ARG is dlopen or points to Java libjvm path --with-jvm-lib-add-rpath Add the libjvm path to the RPATH (no by default) --with-rasdaman=DIR Include rasdaman support (DIR is rasdaman's install dir). --with-armadillo=ARG Include Armadillo support for faster TPS transform computation (ARG=yes/no/path to armadillo install root) [default=no] @@ -29491,7 +29491,14 @@ if test "${with_jvm_lib_add_rpath+set}" = set; then : fi - if test "x$with_jvm_lib" != "x"; then + if test "x$with_jvm_lib" = "xdlopen"; then + +cat >>confdefs.h <<_ACEOF +#define JVM_LIB_DLOPEN 1 +_ACEOF + + JVM_LIB="-ldl" + elif test "x$with_jvm_lib" != "x"; then if test -d "$with_jvm_lib"; then saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -L$with_jvm_lib" diff --git a/configure.in b/configure.in index 91efa5a32a..546ff04049 100644 --- a/configure.in +++ b/configure.in @@ -4213,11 +4213,14 @@ if test "$with_mdb" = "yes" ; then AC_MSG_ERROR("--with-java must be specified.") fi - AC_ARG_WITH(jvm-lib, [ --with-jvm-lib=[ARG] ARG points to Java libjvm path],,) + AC_ARG_WITH(jvm-lib, [ --with-jvm-lib=[ARG] ARG is dlopen or points to Java libjvm path],,) AC_ARG_WITH(jvm-lib-add-rpath,[ --with-jvm-lib-add-rpath Add the libjvm path to the RPATH (no by default)],,) - if test "x$with_jvm_lib" != "x"; then + if test "x$with_jvm_lib" = "xdlopen"; then + AC_DEFINE_UNQUOTED(JVM_LIB_DLOPEN, 1, [Define to 1 if libjvm.so should be dlopen'd]) + JVM_LIB="-ldl" + elif test "x$with_jvm_lib" != "x"; then if test -d "$with_jvm_lib"; then saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -L$with_jvm_lib" diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp index b068adf777..bc54a115df 100644 --- a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp +++ b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp @@ -29,6 +29,11 @@ #include "ogr_mdb.h" +#if JVM_LIB_DLOPEN +#include +#include +#endif + CPL_CVSID("$Id: ogrmdbjackcess.cpp 27044 2014-03-16 23:41:27Z rouault $"); static JavaVM *jvm_static = NULL; @@ -161,9 +166,41 @@ int OGRMDBJavaEnv::Init() { JavaVM* vmBuf[1]; jsize nVMs; + int ret = 0; + +#if JVM_LIB_DLOPEN + const char *jvmLibPtr = "libjvm.so"; + char jvmLib[PATH_MAX]; + + FILE *javaCmd = popen("\"${JAVA_HOME}${JAVA_HOME:+/bin/}java\" -XshowSettings 2>&1 | sed -n '/\\bsun\\.boot\\.library\\.path =/s:.* = \\(.*\\):\\1/server/libjvm.so:p'", "r"); + + if (javaCmd != NULL) + { + size_t javaCmdRead = fread(jvmLib, 1, PATH_MAX, javaCmd); + ret = pclose(javaCmd); + + if (ret == 0 && javaCmdRead >= 2) + { + /* Chomp the new line */ + jvmLib[javaCmdRead - 1] = '\0'; + jvmLibPtr = jvmLib; + } + } + + jint (*pfnJNI_GetCreatedJavaVMs)(JavaVM **, jsize, jsize *); + pfnJNI_GetCreatedJavaVMs = (jint (*)(JavaVM **, jsize, jsize *)) + CPLGetSymbol(jvmLibPtr, "JNI_GetCreatedJavaVMs"); + + if (pfnJNI_GetCreatedJavaVMs == NULL) + return FALSE; + else + ret = pfnJNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs); +#else + ret = JNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs); +#endif /* Are we already called from Java ? */ - if (JNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs) == JNI_OK && nVMs == 1) + if (ret == JNI_OK && nVMs == 1) { jvm = vmBuf[0]; if (jvm->GetEnv((void **)&env, JNI_VERSION_1_2) == JNI_OK) @@ -194,8 +231,22 @@ int OGRMDBJavaEnv::Init() args.nOptions = 0; args.ignoreUnrecognized = JNI_FALSE; - int ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args); - if (ret != 0 || jvm == NULL || env == NULL) +#if JVM_LIB_DLOPEN + jint (*pfnJNI_CreateJavaVM)(JavaVM **, void **, void *); + pfnJNI_CreateJavaVM = (jint (*)(JavaVM **, void **, void *)) + CPLGetSymbol(jvmLibPtr, "JNI_CreateJavaVM"); + + if (pfnJNI_CreateJavaVM == NULL) + return FALSE; + else + ret = pfnJNI_CreateJavaVM(&jvm, (void **)&env, &args); +#else + ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args); +#endif + + CPLFree(pszClassPathOption); + + if (ret != JNI_OK || jvm == NULL || env == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "JNI_CreateJavaVM failed (%d)", ret); return FALSE; diff --git a/port/cpl_config.h.in b/port/cpl_config.h.in index 313729fd3e..e8fa21140a 100644 --- a/port/cpl_config.h.in +++ b/port/cpl_config.h.in @@ -161,6 +161,9 @@ /* For .cpp files, define as const if the declaration of iconv() needs const. */ #undef ICONV_CPP_CONST +/* Define to 1 if libjvm.so should be dlopen'd */ +#undef JVM_LIB_DLOPEN + /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR -- 2.11.0 From cd6bbb60ced62b6176482e86c54ab618e2592ac8 Mon Sep 17 00:00:00 2001 From: James Le Cuirot Date: Thu, 25 Aug 2016 21:26:20 +0100 Subject: [PATCH 2/2] Fetch jackcess classpath using java-config instead of using CLASSPATH --- gdal/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp index bc54a115df..5b0972677e 100644 --- a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp +++ b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp @@ -218,19 +218,37 @@ int OGRMDBJavaEnv::Init() JavaVMInitArgs args; JavaVMOption options[1]; args.version = JNI_VERSION_1_2; - const char* pszClassPath = CPLGetConfigOption("CLASSPATH", NULL); - CPLString osClassPathOption; + + FILE *javaCmd = popen("java-config --with-dependencies --classpath=jackcess-1", "r"); + + const char* pszClassPath = NULL; + if (javaCmd != NULL) + { + pszClassPath = CPLReadLine(javaCmd); + ret = pclose(javaCmd); + + if (ret != 0) + pszClassPath = NULL; + } + + if (pszClassPath == NULL) + pszClassPath = CPLGetConfigOption("CLASSPATH", NULL); + + char* pszClassPathOption = NULL; if (pszClassPath) { args.nOptions = 1; - osClassPathOption.Printf("-Djava.class.path=%s", pszClassPath); - options[0].optionString = (char*) osClassPathOption.c_str(); + pszClassPathOption = CPLStrdup(CPLSPrintf("-Djava.class.path=%s", pszClassPath)); + options[0].optionString = pszClassPathOption; args.options = options; } else args.nOptions = 0; args.ignoreUnrecognized = JNI_FALSE; + if (javaCmd != NULL) + CPLReadLine(NULL); + #if JVM_LIB_DLOPEN jint (*pfnJNI_CreateJavaVM)(JavaVM **, void **, void *); pfnJNI_CreateJavaVM = (jint (*)(JavaVM **, void **, void *)) -- 2.11.0