diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 99559cee287..e4bab3410c1 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1534,6 +1534,56 @@ bool os::set_boot_path(char fileSep, char pathSep) { return false; } +static char* _image_release_file_content = nullptr; + +void os::read_image_release_file() { + assert(_image_release_file_content == nullptr, "release file content must not be already set"); + const char* home = Arguments::get_java_home(); + stringStream ss; + ss.print("%s/release", home); + + FILE* file = fopen(ss.base(), "rb"); + if (file == nullptr) { + return; + } + fseek(file, 0, SEEK_END); + long sz = ftell(file); + if (sz == -1) { + return; + } + fseek(file, 0, SEEK_SET); + + char* tmp = (char*) os::malloc(sz + 1, mtInternal); + if (tmp == nullptr) { + fclose(file); + return; + } + + size_t elements_read = fread(tmp, 1, sz, file); + if (elements_read < (size_t)sz) { + tmp[elements_read] = '\0'; + } else { + tmp[sz] = '\0'; + } + // issues with \r in line endings on Windows, so better replace those + for (size_t i = 0; i < elements_read; i++) { + if (tmp[i] == '\r') { + tmp[i] = ' '; + } + } + Atomic::release_store(&_image_release_file_content, tmp); + fclose(file); +} + +void os::print_image_release_file(outputStream* st) { + char* ifrc = Atomic::load_acquire(&_image_release_file_content); + if (ifrc != nullptr) { + st->print_cr("%s", ifrc); + } else { + st->print_cr(""); + } +} + bool os::file_exists(const char* filename) { struct stat statbuf; if (filename == nullptr || strlen(filename) == 0) { diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 242959034af..16a74cd7ea9 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -670,6 +670,11 @@ class os: AllStatic { static FILE* fopen(const char* path, const char* mode); static jlong lseek(int fd, jlong offset, int whence); static bool file_exists(const char* file); + + // read/store and print the release file of the image + static void read_image_release_file(); + static void print_image_release_file(outputStream* st); + // This function, on Windows, canonicalizes a given path (see os_windows.cpp for details). // On Posix, this function is a noop: it does not change anything and just returns // the input pointer. diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 1d515c9fe7d..203062582a0 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -425,6 +425,19 @@ void Threads::initialize_jsr292_core_classes(TRAPS) { } } +// One-shot PeriodicTask subclass for reading the release file +class ReadReleaseFileTask : public PeriodicTask { + public: + ReadReleaseFileTask() : PeriodicTask(100) {} + + virtual void task() { + os::read_image_release_file(); + + // Reclaim our storage and disenroll ourself. + delete this; + } +}; + jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { extern void JDK_Version_init(); @@ -580,6 +593,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { return status; } + // Have the WatcherThread read the release file in the background. + ReadReleaseFileTask* read_task = new ReadReleaseFileTask(); + read_task->enroll(); + // Create WatcherThread as soon as we can since we need it in case // of hangs during error reporting. WatcherThread::start(); diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index ccd31269d0d..e1940123d67 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1259,6 +1259,10 @@ void VMError::report(outputStream* st, bool _verbose) { LogConfiguration::describe_current_configuration(st); st->cr(); + STEP_IF("printing release file content", _verbose) + st->print_cr("Release file:"); + os::print_image_release_file(st); + STEP_IF("printing all environment variables", _verbose) os::print_environment_variables(st, env_list); st->cr(); @@ -1439,6 +1443,10 @@ void VMError::print_vm_info(outputStream* st) { LogConfiguration::describe(st); st->cr(); + // STEP("printing release file content") + st->print_cr("Release file:"); + os::print_image_release_file(st); + // STEP("printing all environment variables") os::print_environment_variables(st, env_list);