8165524: Better detect JRE that Linux JLI will be using
authorksrini
Wed, 14 Sep 2016 06:46:19 -0700
changeset 40945 f241705723ea
parent 40944 dba53de83476
child 40946 362ab0ff2d9a
8165524: Better detect JRE that Linux JLI will be using Reviewed-by: ksrini Contributed-by: chris.bensen@oracle.com
jdk/src/java.base/share/native/libjli/java.h
jdk/src/java.base/unix/native/libjli/java_md_common.c
jdk/src/java.base/unix/native/libjli/java_md_solinux.c
jdk/src/java.base/windows/native/libjli/java_md.c
jdk/src/java.base/windows/native/libjli/java_md.h
--- a/jdk/src/java.base/share/native/libjli/java.h	Wed Sep 14 14:04:14 2016 +0100
+++ b/jdk/src/java.base/share/native/libjli/java.h	Wed Sep 14 06:46:19 2016 -0700
@@ -112,6 +112,9 @@
 jboolean
 GetApplicationHome(char *buf, jint bufsize);
 
+jboolean
+GetApplicationHomeFromDll(char *buf, jint bufsize);
+
 #define GetArch() GetArchPath(CURRENT_DATA_MODEL)
 
 /*
--- a/jdk/src/java.base/unix/native/libjli/java_md_common.c	Wed Sep 14 14:04:14 2016 +0100
+++ b/jdk/src/java.base/unix/native/libjli/java_md_common.c	Wed Sep 14 06:46:19 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,49 @@
 #include "java.h"
 
 /*
- * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put
- * "/foo" into buf.
+ * Find the last occurrence of a string
+ */
+char* findLastPathComponent(char *buffer, const char *comp) {
+    char* t = buffer;
+    char* p = NULL;
+    size_t l = JLI_StrLen(comp);
+    t = JLI_StrStr(t, comp);
+
+    while (t != NULL) {
+        p = t;
+        t += l;
+        t = JLI_StrStr(t, comp);
+    }
+    return p;
+}
+
+/*
+ * Removes the trailing file name and any intermediate platform
+ * directories, if any, and its enclosing directory.
+ * Ex: if a buffer contains "/foo/bin/javac" or "/foo/bin/x64/javac", the
+ * truncated resulting buffer will contain "/foo".
+ */
+jboolean
+TruncatePath(char *buf)
+{
+    // try bin directory, maybe an executable
+    char *p = findLastPathComponent(buf, "/bin/");
+    if (p != NULL) {
+        *p = '\0';
+        return JNI_TRUE;
+    }
+    // try lib directory, maybe a library
+    p = findLastPathComponent(buf, "/lib/");
+    if (p != NULL) {
+        *p = '\0';
+        return JNI_TRUE;
+    }
+    return JNI_FALSE;
+}
+
+/*
+ * Retrieves the path to the JRE home by locating the executable file
+ * of the current process and then truncating the path to the executable
  */
 jboolean
 GetApplicationHome(char *buf, jint bufsize)
@@ -38,26 +79,27 @@
     } else {
         return JNI_FALSE;
     }
+    return TruncatePath(buf);
+}
 
-    if (JLI_StrRChr(buf, '/') == 0) {
-        buf[0] = '\0';
-        return JNI_FALSE;
-    }
-    *(JLI_StrRChr(buf, '/')) = '\0';    /* executable file      */
-    if (JLI_StrLen(buf) < 4 || JLI_StrRChr(buf, '/') == 0) {
-        buf[0] = '\0';
-        return JNI_FALSE;
+/*
+ * Retrieves the path to the JRE home by locating the
+ * shared library and then truncating the path to it.
+ */
+jboolean
+GetApplicationHomeFromDll(char *buf, jint bufsize)
+{
+    /* try to find ourselves instead */
+    Dl_info info;
+    if (dladdr((void*)&GetApplicationHomeFromDll, &info) != 0) {
+        char *path = realpath(info.dli_fname, buf);
+        if (path == buf) {
+            return TruncatePath(buf);
+        }
     }
-    if (JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0)
-        *(JLI_StrRChr(buf, '/')) = '\0';        /* sparcv9 or amd64     */
-    if (JLI_StrLen(buf) < 4 || JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0) {
-        buf[0] = '\0';
-        return JNI_FALSE;
-    }
-    *(JLI_StrRChr(buf, '/')) = '\0';    /* bin                  */
+    return JNI_FALSE;
+}
 
-    return JNI_TRUE;
-}
 /*
  * Return true if the named program exists
  */
--- a/jdk/src/java.base/unix/native/libjli/java_md_solinux.c	Wed Sep 14 14:04:14 2016 +0100
+++ b/jdk/src/java.base/unix/native/libjli/java_md_solinux.c	Wed Sep 14 06:46:19 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -666,6 +666,7 @@
 GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
 {
     char libjava[MAXPATHLEN];
+    struct stat s;
 
     if (GetApplicationHome(path, pathsize)) {
         /* Is JRE co-located with the application? */
@@ -688,6 +689,14 @@
         }
     }
 
+    if (GetApplicationHomeFromDll(path, pathsize)) {
+        JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch);
+        if (stat(libjava, &s) == 0) {
+            JLI_TraceLauncher("JRE path is %s\n", path);
+            return JNI_TRUE;
+        }
+    }
+
     if (!speculative)
       JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
     return JNI_FALSE;
--- a/jdk/src/java.base/windows/native/libjli/java_md.c	Wed Sep 14 14:04:14 2016 +0100
+++ b/jdk/src/java.base/windows/native/libjli/java_md.c	Wed Sep 14 06:46:19 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -348,7 +348,6 @@
 
     JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
     return JNI_FALSE;
-
 }
 
 /*
@@ -423,11 +422,11 @@
     *JLI_StrRChr(buf, '\\') = '\0'; /* remove .exe file name */
     if ((cp = JLI_StrRChr(buf, '\\')) == 0) {
         /* This happens if the application is in a drive root, and
-        * there is no bin directory. */
+         * there is no bin directory. */
         buf[0] = '\0';
         return JNI_FALSE;
     }
-    *cp = '\0';  /* remove the bin\ part */
+    *cp = '\0'; /* remove the bin\ part */
     return JNI_TRUE;
 }
 
@@ -449,16 +448,16 @@
 jboolean
 GetApplicationHomeFromDll(char *buf, jint bufsize)
 {
-    HMODULE hModule;
-    DWORD dwFlags =
-        GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
-        GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
+    HMODULE module;
+    DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+                  GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
 
-    if (GetModuleHandleEx(dwFlags, (LPCSTR)&GetJREPath, &hModule) == 0) {
-        return JNI_FALSE;
-    };
-    GetModuleFileName(hModule, buf, bufsize);
-    return TruncatePath(buf);
+    if (GetModuleHandleEx(flags, (LPCSTR)&GetJREPath, &module) != 0) {
+        if (GetModuleFileName(module, buf, bufsize) != 0) {
+            return TruncatePath(buf);
+        }
+    }
+    return JNI_FALSE;
 }
 
 /*
--- a/jdk/src/java.base/windows/native/libjli/java_md.h	Wed Sep 14 14:04:14 2016 +0100
+++ b/jdk/src/java.base/windows/native/libjli/java_md.h	Wed Sep 14 06:46:19 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,4 @@
 
 int UnsetEnv(char *name);
 
-jboolean
-GetApplicationHomeFromDll(char *buf, jint bufsize);
-
 #endif /* JAVA_MD_H */