From a7b5545cb80ded72472e2596a808e9460a1f71b0 Mon Sep 17 00:00:00 2001 From: Chris Bensen Date: Wed, 14 Sep 2016 06:46:19 -0700 Subject: [PATCH] 8165524: Better detect JRE that Linux JLI will be using Reviewed-by: ksrini --- jdk/src/java.base/share/native/libjli/java.h | 3 + .../unix/native/libjli/java_md_common.c | 86 ++++++++++++++----- .../unix/native/libjli/java_md_solinux.c | 11 ++- .../java.base/windows/native/libjli/java_md.c | 25 +++--- .../java.base/windows/native/libjli/java_md.h | 5 +- 5 files changed, 90 insertions(+), 40 deletions(-) diff --git a/jdk/src/java.base/share/native/libjli/java.h b/jdk/src/java.base/share/native/libjli/java.h index 41a232714c8..b5056de84a9 100644 --- a/jdk/src/java.base/share/native/libjli/java.h +++ b/jdk/src/java.base/share/native/libjli/java.h @@ -112,6 +112,9 @@ GetXUsagePath(char *buf, jint bufsize); jboolean GetApplicationHome(char *buf, jint bufsize); +jboolean +GetApplicationHomeFromDll(char *buf, jint bufsize); + #define GetArch() GetArchPath(CURRENT_DATA_MODEL) /* diff --git a/jdk/src/java.base/unix/native/libjli/java_md_common.c b/jdk/src/java.base/unix/native/libjli/java_md_common.c index 48c0d8b377e..3c3c4bda969 100644 --- a/jdk/src/java.base/unix/native/libjli/java_md_common.c +++ b/jdk/src/java.base/unix/native/libjli/java_md_common.c @@ -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 @@ GetApplicationHome(char *buf, jint bufsize) } else { return JNI_FALSE; } - - 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; - } - 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_TRUE; + return TruncatePath(buf); } + +/* + * 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); + } + } + return JNI_FALSE; +} + /* * Return true if the named program exists */ diff --git a/jdk/src/java.base/unix/native/libjli/java_md_solinux.c b/jdk/src/java.base/unix/native/libjli/java_md_solinux.c index 38d8834a932..b9091aaead3 100644 --- a/jdk/src/java.base/unix/native/libjli/java_md_solinux.c +++ b/jdk/src/java.base/unix/native/libjli/java_md_solinux.c @@ -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 @@ static jboolean 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 @@ GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative) } } + 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; diff --git a/jdk/src/java.base/windows/native/libjli/java_md.c b/jdk/src/java.base/windows/native/libjli/java_md.c index 3b031d59dcc..3d29357542b 100644 --- a/jdk/src/java.base/windows/native/libjli/java_md.c +++ b/jdk/src/java.base/windows/native/libjli/java_md.c @@ -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 @@ GetJREPath(char *path, jint pathsize) JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL); return JNI_FALSE; - } /* @@ -423,11 +422,11 @@ TruncatePath(char *buf) *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 @@ GetApplicationHome(char *buf, jint bufsize) 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; } /* diff --git a/jdk/src/java.base/windows/native/libjli/java_md.h b/jdk/src/java.base/windows/native/libjli/java_md.h index ec3131f6b61..a2392eba8fc 100644 --- a/jdk/src/java.base/windows/native/libjli/java_md.h +++ b/jdk/src/java.base/windows/native/libjli/java_md.h @@ -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 @@ extern jlong Counter2Micros(jlong counts); int UnsetEnv(char *name); -jboolean -GetApplicationHomeFromDll(char *buf, jint bufsize); - #endif /* JAVA_MD_H */