8165524: Better detect JRE that Linux JLI will be using
Reviewed-by: ksrini
Contributed-by: chris.bensen@oracle.com
--- 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 */