8315220: Event NativeLibraryLoad breaks invariant by taking a stacktrace when thread is in state _thread_in_native
Reviewed-by: mbaesken, egahlin
This commit is contained in:
parent
8f7e29b2cd
commit
1cae0f53a9
@ -81,7 +81,7 @@
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/vmError.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/support/jfrNativeLibraryLoadEvent.hpp"
|
||||
#endif
|
||||
|
||||
// put OS-includes here (sorted alphabetically)
|
||||
@ -1116,11 +1116,6 @@ void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if INCLUDE_JFR
|
||||
EventNativeLibraryLoad event;
|
||||
event.set_name(filename);
|
||||
#endif
|
||||
|
||||
// RTLD_LAZY has currently the same behavior as RTLD_NOW
|
||||
// The dl is loaded immediately with all its dependants.
|
||||
int dflags = RTLD_LAZY;
|
||||
@ -1131,19 +1126,14 @@ void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
dflags |= RTLD_MEMBER;
|
||||
}
|
||||
|
||||
void * result= ::dlopen(filename, dflags);
|
||||
void* result;
|
||||
JFR_ONLY(NativeLibraryLoadEvent load_event(filename, &result);)
|
||||
result = ::dlopen(filename, dflags);
|
||||
if (result != nullptr) {
|
||||
Events::log_dll_message(nullptr, "Loaded shared library %s", filename);
|
||||
// Reload dll cache. Don't do this in signal handling.
|
||||
LoadedLibraries::reload();
|
||||
log_info(os)("shared library load of %s was successful", filename);
|
||||
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(true);
|
||||
event.set_errorMessage(nullptr);
|
||||
event.commit();
|
||||
#endif
|
||||
|
||||
return result;
|
||||
} else {
|
||||
// error analysis when dlopen fails
|
||||
@ -1157,12 +1147,7 @@ void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
}
|
||||
Events::log_dll_message(nullptr, "Loading shared library %s failed, %s", filename, error_report);
|
||||
log_info(os)("shared library load of %s failed, %s", filename, error_report);
|
||||
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage(error_report);
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(load_event.set_error_msg(error_report);)
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -71,6 +71,7 @@
|
||||
#include "utilities/vmError.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/support/jfrNativeLibraryLoadEvent.hpp"
|
||||
#endif
|
||||
|
||||
// put OS-includes here
|
||||
@ -979,21 +980,13 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
#else
|
||||
log_info(os)("attempting shared library load of %s", filename);
|
||||
|
||||
#if INCLUDE_JFR
|
||||
EventNativeLibraryLoad event;
|
||||
event.set_name(filename);
|
||||
#endif
|
||||
|
||||
void * result= ::dlopen(filename, RTLD_LAZY);
|
||||
void* result;
|
||||
JFR_ONLY(NativeLibraryLoadEvent load_event(filename, &result);)
|
||||
result = ::dlopen(filename, RTLD_LAZY);
|
||||
if (result != nullptr) {
|
||||
Events::log_dll_message(nullptr, "Loaded shared library %s", filename);
|
||||
// Successful loading
|
||||
log_info(os)("shared library load of %s was successful", filename);
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(true);
|
||||
event.set_errorMessage(nullptr);
|
||||
event.commit();
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1008,11 +1001,7 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
}
|
||||
Events::log_dll_message(nullptr, "Loading shared library %s failed, %s", filename, error_report);
|
||||
log_info(os)("shared library load of %s failed, %s", filename, error_report);
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage(error_report);
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(load_event.set_error_msg(error_report);)
|
||||
|
||||
return nullptr;
|
||||
#endif // STATIC_BUILD
|
||||
@ -1024,21 +1013,13 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
#else
|
||||
log_info(os)("attempting shared library load of %s", filename);
|
||||
|
||||
#if INCLUDE_JFR
|
||||
EventNativeLibraryLoad event;
|
||||
event.set_name(filename);
|
||||
#endif
|
||||
|
||||
void * result= ::dlopen(filename, RTLD_LAZY);
|
||||
void* result;
|
||||
JFR_ONLY(NativeLibraryLoadEvent load_event(filename, &result);)
|
||||
result = ::dlopen(filename, RTLD_LAZY);
|
||||
if (result != nullptr) {
|
||||
Events::log_dll_message(nullptr, "Loaded shared library %s", filename);
|
||||
// Successful loading
|
||||
log_info(os)("shared library load of %s was successful", filename);
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(true);
|
||||
event.set_errorMessage(nullptr);
|
||||
event.commit();
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1055,11 +1036,7 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
}
|
||||
Events::log_dll_message(nullptr, "Loading shared library %s failed, %s", filename, error_report);
|
||||
log_info(os)("shared library load of %s failed, %s", filename, error_report);
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage(error_report);
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(load_event.set_error_msg(error_report);)
|
||||
int diag_msg_max_length=ebuflen-strlen(ebuf);
|
||||
char* diag_msg_buf=ebuf+strlen(ebuf);
|
||||
|
||||
|
@ -82,6 +82,7 @@
|
||||
#include "utilities/vmError.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/support/jfrNativeLibraryLoadEvent.hpp"
|
||||
#endif
|
||||
|
||||
// put OS-includes here
|
||||
@ -1794,15 +1795,10 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void * os::Linux::dlopen_helper(const char *filename, char *ebuf,
|
||||
int ebuflen) {
|
||||
void * result = ::dlopen(filename, RTLD_LAZY);
|
||||
|
||||
#if INCLUDE_JFR
|
||||
EventNativeLibraryLoad event;
|
||||
event.set_name(filename);
|
||||
#endif
|
||||
|
||||
void * os::Linux::dlopen_helper(const char *filename, char *ebuf, int ebuflen) {
|
||||
void* result;
|
||||
JFR_ONLY(NativeLibraryLoadEvent load_event(filename, &result);)
|
||||
result = ::dlopen(filename, RTLD_LAZY);
|
||||
if (result == nullptr) {
|
||||
const char* error_report = ::dlerror();
|
||||
if (error_report == nullptr) {
|
||||
@ -1814,19 +1810,10 @@ void * os::Linux::dlopen_helper(const char *filename, char *ebuf,
|
||||
}
|
||||
Events::log_dll_message(nullptr, "Loading shared library %s failed, %s", filename, error_report);
|
||||
log_info(os)("shared library load of %s failed, %s", filename, error_report);
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage(error_report);
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(load_event.set_error_msg(error_report);)
|
||||
} else {
|
||||
Events::log_dll_message(nullptr, "Loaded shared library %s", filename);
|
||||
log_info(os)("shared library load of %s was successful", filename);
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(true);
|
||||
event.set_errorMessage(nullptr);
|
||||
event.commit();
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/vmError.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/support/jfrNativeLibraryLoadEvent.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef AIX
|
||||
@ -728,10 +728,7 @@ void os::dll_unload(void *lib) {
|
||||
}
|
||||
#endif // LINUX
|
||||
|
||||
#if INCLUDE_JFR
|
||||
EventNativeLibraryUnload event;
|
||||
event.set_name(l_path);
|
||||
#endif
|
||||
JFR_ONLY(NativeLibraryUnloadEvent unload_event(l_path);)
|
||||
|
||||
if (l_path == nullptr) {
|
||||
l_path = "<not available>";
|
||||
@ -742,11 +739,7 @@ void os::dll_unload(void *lib) {
|
||||
Events::log_dll_message(nullptr, "Unloaded shared library \"%s\" [" INTPTR_FORMAT "]",
|
||||
l_path, p2i(lib));
|
||||
log_info(os)("Unloaded shared library \"%s\" [" INTPTR_FORMAT "]", l_path, p2i(lib));
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(true);
|
||||
event.set_errorMessage(nullptr);
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(unload_event.set_result(true);)
|
||||
} else {
|
||||
const char* error_report = ::dlerror();
|
||||
if (error_report == nullptr) {
|
||||
@ -757,11 +750,7 @@ void os::dll_unload(void *lib) {
|
||||
l_path, p2i(lib), error_report);
|
||||
log_info(os)("Attempt to unload shared library \"%s\" [" INTPTR_FORMAT "] failed, %s",
|
||||
l_path, p2i(lib), error_report);
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage(error_report);
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(unload_event.set_error_msg(error_report);)
|
||||
}
|
||||
// Update the dll cache
|
||||
AIX_ONLY(LoadedLibraries::reload());
|
||||
|
@ -80,6 +80,7 @@
|
||||
#include "windbghelp.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/support/jfrNativeLibraryLoadEvent.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
@ -1246,33 +1247,22 @@ void os::dll_unload(void *lib) {
|
||||
snprintf(name, MAX_PATH, "<not available>");
|
||||
}
|
||||
|
||||
#if INCLUDE_JFR
|
||||
EventNativeLibraryUnload event;
|
||||
event.set_name(name);
|
||||
#endif
|
||||
JFR_ONLY(NativeLibraryUnloadEvent unload_event(name);)
|
||||
|
||||
if (::FreeLibrary((HMODULE)lib)) {
|
||||
Events::log_dll_message(nullptr, "Unloaded dll \"%s\" [" INTPTR_FORMAT "]", name, p2i(lib));
|
||||
log_info(os)("Unloaded dll \"%s\" [" INTPTR_FORMAT "]", name, p2i(lib));
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(true);
|
||||
event.set_errorMessage(nullptr);
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(unload_event.set_result(true);)
|
||||
} else {
|
||||
const DWORD errcode = ::GetLastError();
|
||||
char buf[500];
|
||||
size_t tl = os::lasterror(buf, sizeof(buf));
|
||||
Events::log_dll_message(nullptr, "Attempt to unload dll \"%s\" [" INTPTR_FORMAT "] failed (error code %d)", name, p2i(lib), errcode);
|
||||
log_info(os)("Attempt to unload dll \"%s\" [" INTPTR_FORMAT "] failed (error code %d)", name, p2i(lib), errcode);
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
if (tl == 0) {
|
||||
os::snprintf(buf, sizeof(buf), "Attempt to unload dll failed (error code %d)", (int) errcode);
|
||||
}
|
||||
event.set_errorMessage(buf);
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(unload_event.set_error_msg(buf);)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1541,21 +1531,14 @@ static int _print_module(const char* fname, address base_address,
|
||||
// same architecture as Hotspot is running on
|
||||
void * os::dll_load(const char *name, char *ebuf, int ebuflen) {
|
||||
log_info(os)("attempting shared library load of %s", name);
|
||||
#if INCLUDE_JFR
|
||||
EventNativeLibraryLoad event;
|
||||
event.set_name(name);
|
||||
#endif
|
||||
void * result = LoadLibrary(name);
|
||||
void* result;
|
||||
JFR_ONLY(NativeLibraryLoadEvent load_event(name, &result);)
|
||||
result = LoadLibrary(name);
|
||||
if (result != nullptr) {
|
||||
Events::log_dll_message(nullptr, "Loaded shared library %s", name);
|
||||
// Recalculate pdb search path if a DLL was loaded successfully.
|
||||
SymbolEngine::recalc_search_path();
|
||||
log_info(os)("shared library load of %s was successful", name);
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(true);
|
||||
event.set_errorMessage(nullptr);
|
||||
event.commit();
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
DWORD errcode = GetLastError();
|
||||
@ -1569,11 +1552,7 @@ void * os::dll_load(const char *name, char *ebuf, int ebuflen) {
|
||||
if (errcode == ERROR_MOD_NOT_FOUND) {
|
||||
strncpy(ebuf, "Can't find dependent libraries", ebuflen - 1);
|
||||
ebuf[ebuflen - 1] = '\0';
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage(ebuf);
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(load_event.set_error_msg(ebuf);)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1584,11 +1563,7 @@ void * os::dll_load(const char *name, char *ebuf, int ebuflen) {
|
||||
// else call os::lasterror to obtain system error message
|
||||
int fd = ::open(name, O_RDONLY | O_BINARY, 0);
|
||||
if (fd < 0) {
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage("open on dll file did not work");
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(load_event.set_error_msg("open on dll file did not work");)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1615,11 +1590,7 @@ void * os::dll_load(const char *name, char *ebuf, int ebuflen) {
|
||||
::close(fd);
|
||||
if (failed_to_get_lib_arch) {
|
||||
// file i/o error - report os::lasterror(...) msg
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage("failed to get lib architecture");
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(load_event.set_error_msg("failed to get lib architecture");)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1664,11 +1635,7 @@ void * os::dll_load(const char *name, char *ebuf, int ebuflen) {
|
||||
// If the architecture is right
|
||||
// but some other error took place - report os::lasterror(...) msg
|
||||
if (lib_arch == running_arch) {
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage("lib architecture matches, but other error occured");
|
||||
event.commit();
|
||||
#endif
|
||||
JFR_ONLY(load_event.set_error_msg("lib architecture matches, but other error occured");)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1682,12 +1649,7 @@ void * os::dll_load(const char *name, char *ebuf, int ebuflen) {
|
||||
"Can't load this .dll (machine code=0x%x) on a %s-bit platform",
|
||||
lib_arch, running_arch_str);
|
||||
}
|
||||
#if INCLUDE_JFR
|
||||
event.set_success(false);
|
||||
event.set_errorMessage(ebuf);
|
||||
event.commit();
|
||||
#endif
|
||||
|
||||
JFR_ONLY(load_event.set_error_msg(ebuf);)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -939,14 +939,14 @@
|
||||
<Field type="ulong" contentType="address" name="topAddress" label="Top Address" description="Ending address of the module, if available" />
|
||||
</Event>
|
||||
|
||||
<Event name="NativeLibraryLoad" category="Java Virtual Machine, Runtime" label="Native Library Load" thread="false" stackTrace="true" startTime="true"
|
||||
<Event name="NativeLibraryLoad" category="Java Virtual Machine, Runtime" label="Native Library Load" thread="true" stackTrace="true" startTime="true"
|
||||
description="Information about a dynamic library or other native image load operation">
|
||||
<Field type="string" name="name" label="Name" />
|
||||
<Field type="boolean" name="success" label="Success" description="Success or failure of the load operation" />
|
||||
<Field type="string" name="errorMessage" label="Error Message" description="In case of a load error, error description" />
|
||||
</Event>
|
||||
|
||||
<Event name="NativeLibraryUnload" category="Java Virtual Machine, Runtime" label="Native Library Unload" thread="false" stackTrace="true" startTime="true"
|
||||
<Event name="NativeLibraryUnload" category="Java Virtual Machine, Runtime" label="Native Library Unload" thread="true" stackTrace="true" startTime="true"
|
||||
description="Information about a dynamic library or other native image unload operation">
|
||||
<Field type="string" name="name" label="Name" />
|
||||
<Field type="boolean" name="success" label="Success" description="Success or failure of the unload operation" />
|
||||
|
123
src/hotspot/share/jfr/support/jfrNativeLibraryLoadEvent.cpp
Normal file
123
src/hotspot/share/jfr/support/jfrNativeLibraryLoadEvent.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/support/jfrNativeLibraryLoadEvent.hpp"
|
||||
#include "jfr/utilities/jfrTime.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
|
||||
JfrNativeLibraryEventBase::JfrNativeLibraryEventBase(const char* name) : _name(name), _error_msg(nullptr), _start_time(nullptr) {}
|
||||
|
||||
JfrNativeLibraryEventBase::~JfrNativeLibraryEventBase() {
|
||||
delete _start_time;
|
||||
}
|
||||
|
||||
const char* JfrNativeLibraryEventBase::name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
JfrTicksWrapper* JfrNativeLibraryEventBase::start_time() const {
|
||||
return _start_time;
|
||||
}
|
||||
|
||||
bool JfrNativeLibraryEventBase::has_start_time() const {
|
||||
return _start_time != nullptr;
|
||||
}
|
||||
|
||||
const char* JfrNativeLibraryEventBase::error_msg() const {
|
||||
return _error_msg;
|
||||
}
|
||||
|
||||
void JfrNativeLibraryEventBase::set_error_msg(const char* error_msg) {
|
||||
assert(_error_msg == nullptr, "invariant");
|
||||
_error_msg = error_msg;
|
||||
}
|
||||
|
||||
/*
|
||||
* The JfrTicks value is heap allocated inside an object of type JfrTicksWrapper.
|
||||
* The reason is that a raw value object of type Ticks is not possible at this
|
||||
* location because this code runs as part of early VM bootstrap, at a moment
|
||||
* where Ticks support is not yet initialized.
|
||||
*/
|
||||
template <typename EventType>
|
||||
static inline JfrTicksWrapper* allocate_start_time() {
|
||||
return EventType::is_enabled() ? new JfrTicksWrapper() : nullptr;
|
||||
}
|
||||
|
||||
NativeLibraryLoadEvent::NativeLibraryLoadEvent(const char* name, void** result) : JfrNativeLibraryEventBase(name), _result(result) {
|
||||
assert(_result != nullptr, "invariant");
|
||||
_start_time = allocate_start_time<EventNativeLibraryLoad>();
|
||||
}
|
||||
|
||||
bool NativeLibraryLoadEvent::success() const {
|
||||
return *_result != nullptr;
|
||||
}
|
||||
|
||||
NativeLibraryUnloadEvent::NativeLibraryUnloadEvent(const char* name) : JfrNativeLibraryEventBase(name), _result(false) {
|
||||
_start_time = allocate_start_time<EventNativeLibraryUnload>();
|
||||
}
|
||||
|
||||
bool NativeLibraryUnloadEvent::success() const {
|
||||
return _result;
|
||||
}
|
||||
|
||||
void NativeLibraryUnloadEvent::set_result(bool result) {
|
||||
_result = result;
|
||||
}
|
||||
|
||||
template <typename EventType, typename HelperType>
|
||||
static void commit(HelperType& helper) {
|
||||
if (!helper.has_start_time()) {
|
||||
return;
|
||||
}
|
||||
EventType event(UNTIMED);
|
||||
event.set_endtime(JfrTicks::now());
|
||||
event.set_starttime(*helper.start_time());
|
||||
event.set_name(helper.name());
|
||||
event.set_errorMessage(helper.error_msg());
|
||||
event.set_success(helper.success());
|
||||
Thread* thread = Thread::current();
|
||||
assert(thread != nullptr, "invariant");
|
||||
if (thread->is_Java_thread()) {
|
||||
JavaThread* jt = JavaThread::cast(thread);
|
||||
if (jt->thread_state() != _thread_in_vm) {
|
||||
assert(jt->thread_state() == _thread_in_native, "invariant");
|
||||
// For a JavaThread to take a JFR stacktrace, it must be in _thread_in_vm. Can safepoint here.
|
||||
ThreadInVMfromNative transition(jt);
|
||||
event.commit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
event.commit();
|
||||
}
|
||||
|
||||
NativeLibraryLoadEvent::~NativeLibraryLoadEvent() {
|
||||
commit<EventNativeLibraryLoad>(*this);
|
||||
}
|
||||
|
||||
NativeLibraryUnloadEvent::~NativeLibraryUnloadEvent() {
|
||||
commit<EventNativeLibraryUnload>(*this);
|
||||
}
|
71
src/hotspot/share/jfr/support/jfrNativeLibraryLoadEvent.hpp
Normal file
71
src/hotspot/share/jfr/support/jfrNativeLibraryLoadEvent.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_JFR_SUPPORT_JFRNATIVELIBRARYLOADEVENT_HPP
|
||||
#define SHARE_JFR_SUPPORT_JFRNATIVELIBRARYLOADEVENT_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
class JfrTicksWrapper;
|
||||
|
||||
/*
|
||||
* Helper types for populating NativeLibrary events.
|
||||
* Event commit is run as part of destructors.
|
||||
*/
|
||||
|
||||
class JfrNativeLibraryEventBase : public StackObj {
|
||||
protected:
|
||||
const char* _name;
|
||||
const char* _error_msg;
|
||||
JfrTicksWrapper* _start_time;
|
||||
JfrNativeLibraryEventBase(const char* name);
|
||||
~JfrNativeLibraryEventBase();
|
||||
public:
|
||||
const char* name() const;
|
||||
const char* error_msg() const;
|
||||
void set_error_msg(const char* error_msg);
|
||||
JfrTicksWrapper* start_time() const;
|
||||
bool has_start_time() const;
|
||||
};
|
||||
|
||||
class NativeLibraryLoadEvent : public JfrNativeLibraryEventBase {
|
||||
private:
|
||||
void** _result;
|
||||
public:
|
||||
NativeLibraryLoadEvent(const char* name, void** result);
|
||||
~NativeLibraryLoadEvent();
|
||||
bool success() const;
|
||||
};
|
||||
|
||||
class NativeLibraryUnloadEvent : public JfrNativeLibraryEventBase {
|
||||
private:
|
||||
bool _result;
|
||||
public:
|
||||
NativeLibraryUnloadEvent(const char* name);
|
||||
~NativeLibraryUnloadEvent();
|
||||
bool success() const;
|
||||
void set_result(bool result);
|
||||
};
|
||||
|
||||
#endif // SHARE_JFR_SUPPORT_JFRNATIVELIBRARYLOADEVENT_HPP
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2023, 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,6 +25,7 @@
|
||||
#ifndef SHARE_JFR_UTILITIES_JFRTIME_HPP
|
||||
#define SHARE_JFR_UTILITIES_JFRTIME_HPP
|
||||
|
||||
#include "jfr/utilities/jfrAllocation.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
|
||||
typedef TimeInstant<CounterRepresentation, FastUnorderedElapsedCounterSource> JfrTicks;
|
||||
@ -41,4 +42,13 @@ class JfrTime {
|
||||
static const void* time_function();
|
||||
};
|
||||
|
||||
// For dynamically allocated Ticks values.
|
||||
class JfrTicksWrapper : public JfrCHeapObj {
|
||||
private:
|
||||
JfrTicks _ticks;
|
||||
public:
|
||||
JfrTicksWrapper() : _ticks(JfrTicks::now()) {}
|
||||
operator JfrTicks() const { return _ticks; }
|
||||
};
|
||||
|
||||
#endif // SHARE_JFR_UTILITIES_JFRTIME_HPP
|
||||
|
@ -23,14 +23,15 @@
|
||||
|
||||
package jdk.jfr.event.runtime;
|
||||
|
||||
import static jdk.test.lib.Asserts.assertNotNull;
|
||||
import static jdk.test.lib.Asserts.assertNull;
|
||||
import static jdk.test.lib.Asserts.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.jfr.Recording;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.jfr.consumer.RecordedFrame;
|
||||
import jdk.jfr.consumer.RecordedMethod;
|
||||
import jdk.jfr.consumer.RecordedStackTrace;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.jfr.EventNames;
|
||||
import jdk.test.lib.jfr.Events;
|
||||
@ -46,25 +47,49 @@ import jdk.test.lib.jfr.Events;
|
||||
public class TestNativeLibraryLoadEvent {
|
||||
|
||||
private final static String EVENT_NAME = EventNames.NativeLibraryLoad;
|
||||
private final static String LOAD_CLASS_NAME = "java.lang.System";
|
||||
private final static String LOAD_METHOD_NAME = "loadLibrary";
|
||||
private final static String LIBRARY = "instrument";
|
||||
private final static String PLATFORM_LIBRARY_NAME = Platform.buildSharedLibraryName(LIBRARY);
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try (Recording recording = new Recording()) {
|
||||
recording.enable(EVENT_NAME);
|
||||
recording.start();
|
||||
System.loadLibrary("instrument");
|
||||
System.loadLibrary(LIBRARY);
|
||||
recording.stop();
|
||||
|
||||
String expectedLib = Platform.buildSharedLibraryName("instrument");
|
||||
boolean expectedLibFound = false;
|
||||
for (RecordedEvent event : Events.fromRecording(recording)) {
|
||||
System.out.println("Event:" + event);
|
||||
String lib = Events.assertField(event, "name").notEmpty().getValue();
|
||||
Events.assertField(event, "success");
|
||||
if (lib.contains(expectedLib)) {
|
||||
expectedLibFound = true;
|
||||
if (validate(event)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
assertTrue(expectedLibFound, "Missing library " + expectedLib);
|
||||
assertTrue(false, "Missing library " + PLATFORM_LIBRARY_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean validate(RecordedEvent event) {
|
||||
assertTrue(event.getEventType().getName().equals(EVENT_NAME));
|
||||
String lib = Events.assertField(event, "name").notEmpty().getValue();
|
||||
System.out.println(lib);
|
||||
if (!lib.endsWith(PLATFORM_LIBRARY_NAME)) {
|
||||
return false;
|
||||
}
|
||||
assertTrue(Events.assertField(event, "success").getValue());
|
||||
assertNull(Events.assertField(event, "errorMessage").getValue());
|
||||
RecordedStackTrace stacktrace = event.getStackTrace();
|
||||
assertNotNull(stacktrace);
|
||||
for (RecordedFrame f : stacktrace.getFrames()) {
|
||||
if (match(f.getMethod())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean match(RecordedMethod method) {
|
||||
assertNotNull(method);
|
||||
System.out.println(method.getType().getName() + "." + method.getName());
|
||||
return method.getName().equals(LOAD_METHOD_NAME) && method.getType().getName().equals(LOAD_CLASS_NAME);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user