mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8241678: Remove PerfData sampling via StatSampler
Reviewed-by: jsjolen, ayang
This commit is contained in:
parent
f30e15411f
commit
6ebae6cded
@ -58,7 +58,6 @@
|
||||
#include "runtime/perfMemory.hpp"
|
||||
#include "runtime/safefetch.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/statSampler.hpp"
|
||||
#include "runtime/threads.hpp"
|
||||
#include "runtime/timer.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
|
||||
@ -53,7 +53,6 @@
|
||||
#include "runtime/perfMemory.hpp"
|
||||
#include "runtime/semaphore.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/statSampler.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/threads.hpp"
|
||||
#include "runtime/timer.hpp"
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
#include "runtime/osThread.hpp"
|
||||
#include "runtime/perfMemory.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/statSampler.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/threads.hpp"
|
||||
#include "runtime/threadSMR.hpp"
|
||||
|
||||
@ -60,7 +60,6 @@
|
||||
#include "runtime/safepointMechanism.hpp"
|
||||
#include "runtime/semaphore.inline.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/statSampler.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/suspendedThreadTask.hpp"
|
||||
#include "runtime/threads.hpp"
|
||||
|
||||
@ -33,8 +33,7 @@
|
||||
|
||||
SpaceCounters::SpaceCounters(const char* name, int ordinal, size_t max_size,
|
||||
MutableSpace* m, GenerationCounters* gc)
|
||||
: _last_used_in_bytes(0), _object_space(m)
|
||||
{
|
||||
: _object_space(m) {
|
||||
if (UsePerfData) {
|
||||
EXCEPTION_MARK;
|
||||
ResourceMark rm;
|
||||
@ -60,7 +59,7 @@ SpaceCounters::SpaceCounters(const char* name, int ordinal, size_t max_size,
|
||||
|
||||
cname = PerfDataManager::counter_name(_name_space, "used");
|
||||
_used = PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes,
|
||||
new UsedHelper(this),
|
||||
_object_space->used_in_bytes(),
|
||||
CHECK);
|
||||
|
||||
cname = PerfDataManager::counter_name(_name_space, "initCapacity");
|
||||
@ -74,21 +73,5 @@ SpaceCounters::~SpaceCounters() {
|
||||
}
|
||||
|
||||
void SpaceCounters::update_used() {
|
||||
size_t new_used = _object_space->used_in_bytes();
|
||||
Atomic::store(&_last_used_in_bytes, new_used);
|
||||
_used->set_value(new_used);
|
||||
}
|
||||
|
||||
jlong SpaceCounters::UsedHelper::take_sample() {
|
||||
// Sampling may occur during GC, possibly while GC is updating the space.
|
||||
// The space can be in an inconsistent state during such an update. We
|
||||
// don't want to block sampling for the duration of a GC. Instead, skip
|
||||
// sampling in that case, using the last recorded value.
|
||||
assert(!Heap_lock->owned_by_self(), "precondition");
|
||||
if (Heap_lock->try_lock()) {
|
||||
size_t new_used = _counters->_object_space->used_in_bytes();
|
||||
Atomic::store(&_counters->_last_used_in_bytes, new_used);
|
||||
Heap_lock->unlock();
|
||||
}
|
||||
return Atomic::load(&_counters->_last_used_in_bytes);
|
||||
_used->set_value(_object_space->used_in_bytes());
|
||||
}
|
||||
|
||||
@ -39,7 +39,6 @@ class SpaceCounters: public CHeapObj<mtGC> {
|
||||
private:
|
||||
PerfVariable* _capacity;
|
||||
PerfVariable* _used;
|
||||
volatile size_t _last_used_in_bytes;
|
||||
|
||||
// Constant PerfData types don't need to retain a reference.
|
||||
// However, it's a good idea to document them here.
|
||||
@ -48,8 +47,6 @@ class SpaceCounters: public CHeapObj<mtGC> {
|
||||
MutableSpace* _object_space;
|
||||
char* _name_space;
|
||||
|
||||
class UsedHelper;
|
||||
|
||||
public:
|
||||
|
||||
SpaceCounters(const char* name, int ordinal, size_t max_size,
|
||||
@ -71,14 +68,4 @@ class SpaceCounters: public CHeapObj<mtGC> {
|
||||
const char* name_space() const { return _name_space; }
|
||||
};
|
||||
|
||||
class SpaceCounters::UsedHelper: public PerfLongSampleHelper {
|
||||
private:
|
||||
SpaceCounters* _counters;
|
||||
|
||||
public:
|
||||
UsedHelper(SpaceCounters* counters) : _counters(counters) { }
|
||||
|
||||
jlong take_sample() override;
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_PARALLEL_SPACECOUNTERS_HPP
|
||||
|
||||
@ -28,8 +28,7 @@
|
||||
|
||||
CSpaceCounters::CSpaceCounters(const char* name, int ordinal, size_t max_size,
|
||||
ContiguousSpace* s, GenerationCounters* gc)
|
||||
: _last_used_in_bytes(0), _space(s)
|
||||
{
|
||||
: _space(s) {
|
||||
if (UsePerfData) {
|
||||
EXCEPTION_MARK;
|
||||
ResourceMark rm;
|
||||
@ -57,7 +56,7 @@ CSpaceCounters::CSpaceCounters(const char* name, int ordinal, size_t max_size,
|
||||
|
||||
cname = PerfDataManager::counter_name(_name_space, "used");
|
||||
_used = PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes,
|
||||
new UsedHelper(this),
|
||||
_space->used(),
|
||||
CHECK);
|
||||
|
||||
cname = PerfDataManager::counter_name(_name_space, "initCapacity");
|
||||
@ -75,26 +74,10 @@ void CSpaceCounters::update_capacity() {
|
||||
}
|
||||
|
||||
void CSpaceCounters::update_used() {
|
||||
size_t new_used = _space->used();
|
||||
Atomic::store(&_last_used_in_bytes, new_used);
|
||||
_used->set_value(new_used);
|
||||
_used->set_value(_space->used());
|
||||
}
|
||||
|
||||
void CSpaceCounters::update_all() {
|
||||
update_used();
|
||||
update_capacity();
|
||||
}
|
||||
|
||||
jlong CSpaceCounters::UsedHelper::take_sample(){
|
||||
// Sampling may occur during GC, possibly while GC is updating the space.
|
||||
// The space can be in an inconsistent state during such an update. We
|
||||
// don't want to block sampling for the duration of a GC. Instead, skip
|
||||
// sampling in that case, using the last recorded value.
|
||||
assert(!Heap_lock->owned_by_self(), "precondition");
|
||||
if (Heap_lock->try_lock()) {
|
||||
size_t new_used = _counters->_space->used();
|
||||
Atomic::store(&_counters->_last_used_in_bytes, new_used);
|
||||
Heap_lock->unlock();
|
||||
}
|
||||
return Atomic::load(&_counters->_last_used_in_bytes);
|
||||
}
|
||||
|
||||
@ -39,7 +39,6 @@ class CSpaceCounters: public CHeapObj<mtGC> {
|
||||
PerfVariable* _capacity;
|
||||
PerfVariable* _used;
|
||||
PerfVariable* _max_capacity;
|
||||
volatile size_t _last_used_in_bytes;
|
||||
|
||||
// Constant PerfData types don't need to retain a reference.
|
||||
// However, it's a good idea to document them here.
|
||||
@ -48,8 +47,6 @@ class CSpaceCounters: public CHeapObj<mtGC> {
|
||||
ContiguousSpace* _space;
|
||||
char* _name_space;
|
||||
|
||||
class UsedHelper;
|
||||
|
||||
public:
|
||||
|
||||
CSpaceCounters(const char* name, int ordinal, size_t max_size,
|
||||
@ -64,14 +61,4 @@ class CSpaceCounters: public CHeapObj<mtGC> {
|
||||
const char* name_space() const { return _name_space; }
|
||||
};
|
||||
|
||||
class CSpaceCounters::UsedHelper : public PerfLongSampleHelper {
|
||||
private:
|
||||
CSpaceCounters* _counters;
|
||||
|
||||
public:
|
||||
UsedHelper(CSpaceCounters* counters) : _counters(counters) { }
|
||||
|
||||
jlong take_sample() override;
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_SERIAL_CSPACECOUNTERS_HPP
|
||||
|
||||
@ -536,6 +536,7 @@ static SpecialFlag const special_jvm_flags[] = {
|
||||
|
||||
// -------------- Obsolete Flags - sorted by expired_in --------------
|
||||
|
||||
{ "PerfDataSamplingInterval", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::jdk(26) },
|
||||
{ "MetaspaceReclaimPolicy", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::undefined() },
|
||||
{ "ZGenerational", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::undefined() },
|
||||
{ "ZMarkStackSpaceLimit", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::undefined() },
|
||||
|
||||
@ -1728,11 +1728,6 @@ const int ObjectAlignmentInBytes = 8;
|
||||
"The string %p in the file name (if present) " \
|
||||
"will be replaced by pid") \
|
||||
\
|
||||
product(int, PerfDataSamplingInterval, 50, \
|
||||
"Data sampling interval (in milliseconds)") \
|
||||
range(PeriodicTask::min_interval, max_jint) \
|
||||
constraint(PerfDataSamplingIntervalFunc, AfterErgo) \
|
||||
\
|
||||
product(bool, PerfDisableSharedMem, false, \
|
||||
"Store performance data in standard memory") \
|
||||
\
|
||||
|
||||
@ -70,7 +70,6 @@
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/javaThread.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/statSampler.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/task.hpp"
|
||||
#include "runtime/threads.hpp"
|
||||
@ -470,10 +469,6 @@ void before_exit(JavaThread* thread, bool halt) {
|
||||
// PeriodicTasks to reduce the likelihood of races.
|
||||
WatcherThread::stop();
|
||||
|
||||
// shut down the StatSampler task
|
||||
StatSampler::disengage();
|
||||
StatSampler::destroy();
|
||||
|
||||
NativeHeapTrimmer::cleanup();
|
||||
|
||||
// Stop concurrent GC threads
|
||||
|
||||
@ -27,8 +27,10 @@
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/mutex.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
@ -38,7 +40,6 @@
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
PerfDataList* PerfDataManager::_all = nullptr;
|
||||
PerfDataList* PerfDataManager::_sampled = nullptr;
|
||||
PerfDataList* PerfDataManager::_constants = nullptr;
|
||||
volatile bool PerfDataManager::_has_PerfData = 0;
|
||||
|
||||
@ -198,20 +199,6 @@ PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v)
|
||||
create_entry(T_LONG, sizeof(jlong));
|
||||
}
|
||||
|
||||
PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u,
|
||||
Variability v, PerfLongSampleHelper* helper)
|
||||
: PerfLong(ns, namep, u, v),
|
||||
_sample_helper(helper) {
|
||||
|
||||
sample();
|
||||
}
|
||||
|
||||
void PerfLongVariant::sample() {
|
||||
if (_sample_helper != nullptr) {
|
||||
*(jlong*)_valuep = _sample_helper->take_sample();
|
||||
}
|
||||
}
|
||||
|
||||
PerfByteArray::PerfByteArray(CounterNS ns, const char* namep, Units u,
|
||||
Variability v, jint length)
|
||||
: PerfData(ns, namep, u, v), _length(length) {
|
||||
@ -266,8 +253,8 @@ void PerfDataManager::destroy() {
|
||||
Atomic::store(&_has_PerfData, false);
|
||||
GlobalCounter::write_synchronize();
|
||||
|
||||
log_debug(perf, datacreation)("Total = %d, Sampled = %d, Constants = %d",
|
||||
_all->length(), _sampled == nullptr ? 0 : _sampled->length(),
|
||||
log_debug(perf, datacreation)("Total = %d, Constants = %d",
|
||||
_all->length(),
|
||||
_constants == nullptr ? 0 : _constants->length());
|
||||
|
||||
for (int index = 0; index < _all->length(); index++) {
|
||||
@ -276,15 +263,13 @@ void PerfDataManager::destroy() {
|
||||
}
|
||||
|
||||
delete(_all);
|
||||
delete(_sampled);
|
||||
delete(_constants);
|
||||
|
||||
_all = nullptr;
|
||||
_sampled = nullptr;
|
||||
_constants = nullptr;
|
||||
}
|
||||
|
||||
void PerfDataManager::add_item(PerfData* p, bool sampled) {
|
||||
void PerfDataManager::add_item(PerfData* p) {
|
||||
|
||||
MutexLocker ml(PerfDataManager_lock);
|
||||
|
||||
@ -306,24 +291,6 @@ void PerfDataManager::add_item(PerfData* p, bool sampled) {
|
||||
_constants->append(p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sampled) {
|
||||
if (_sampled == nullptr) {
|
||||
_sampled = new PerfDataList(1);
|
||||
}
|
||||
_sampled->append(p);
|
||||
}
|
||||
}
|
||||
|
||||
PerfDataList* PerfDataManager::sampled() {
|
||||
|
||||
MutexLocker ml(PerfDataManager_lock);
|
||||
|
||||
if (_sampled == nullptr)
|
||||
return nullptr;
|
||||
|
||||
PerfDataList* clone = _sampled->clone();
|
||||
return clone;
|
||||
}
|
||||
|
||||
char* PerfDataManager::counter_name(const char* ns, const char* name) {
|
||||
@ -362,7 +329,7 @@ PerfStringConstant* PerfDataManager::create_string_constant(CounterNS ns,
|
||||
THROW_NULL(vmSymbols::java_lang_OutOfMemoryError());
|
||||
}
|
||||
|
||||
add_item(p, false);
|
||||
add_item(p);
|
||||
|
||||
return p;
|
||||
}
|
||||
@ -380,7 +347,7 @@ PerfLongConstant* PerfDataManager::create_long_constant(CounterNS ns,
|
||||
THROW_NULL(vmSymbols::java_lang_OutOfMemoryError());
|
||||
}
|
||||
|
||||
add_item(p, false);
|
||||
add_item(p);
|
||||
|
||||
return p;
|
||||
}
|
||||
@ -403,7 +370,7 @@ PerfStringVariable* PerfDataManager::create_string_variable(CounterNS ns,
|
||||
THROW_NULL(vmSymbols::java_lang_OutOfMemoryError());
|
||||
}
|
||||
|
||||
add_item(p, false);
|
||||
add_item(p);
|
||||
|
||||
return p;
|
||||
}
|
||||
@ -421,29 +388,7 @@ PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
|
||||
THROW_NULL(vmSymbols::java_lang_OutOfMemoryError());
|
||||
}
|
||||
|
||||
add_item(p, false);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
|
||||
const char* name,
|
||||
PerfData::Units u,
|
||||
PerfSampleHelper* sh,
|
||||
TRAPS) {
|
||||
|
||||
// Sampled counters not supported if UsePerfData is false
|
||||
if (!UsePerfData) return nullptr;
|
||||
|
||||
PerfLongVariable* p = new PerfLongVariable(ns, name, u, sh);
|
||||
|
||||
if (!p->is_valid()) {
|
||||
// allocation of native resources failed.
|
||||
delete p;
|
||||
THROW_NULL(vmSymbols::java_lang_OutOfMemoryError());
|
||||
}
|
||||
|
||||
add_item(p, true);
|
||||
add_item(p);
|
||||
|
||||
return p;
|
||||
}
|
||||
@ -461,31 +406,133 @@ PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
|
||||
THROW_NULL(vmSymbols::java_lang_OutOfMemoryError());
|
||||
}
|
||||
|
||||
add_item(p, false);
|
||||
add_item(p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
|
||||
const char* name,
|
||||
PerfData::Units u,
|
||||
PerfSampleHelper* sh,
|
||||
TRAPS) {
|
||||
/*
|
||||
* Call into java.lang.System.getProperty to check that the value of the
|
||||
* specified property matches
|
||||
*/
|
||||
void PerfDataManager::assert_system_property(const char* name, const char* value, TRAPS) {
|
||||
#ifdef ASSERT
|
||||
ResourceMark rm(THREAD);
|
||||
|
||||
// Sampled counters not supported if UsePerfData is false
|
||||
if (!UsePerfData) return nullptr;
|
||||
// setup the arguments to getProperty
|
||||
Handle key_str = java_lang_String::create_from_str(name, CHECK);
|
||||
|
||||
PerfLongCounter* p = new PerfLongCounter(ns, name, u, sh);
|
||||
// return value
|
||||
JavaValue result(T_OBJECT);
|
||||
|
||||
if (!p->is_valid()) {
|
||||
// allocation of native resources failed.
|
||||
delete p;
|
||||
THROW_NULL(vmSymbols::java_lang_OutOfMemoryError());
|
||||
// public static String getProperty(String key, String def);
|
||||
JavaCalls::call_static(&result, vmClasses::System_klass(),
|
||||
vmSymbols::getProperty_name(),
|
||||
vmSymbols::string_string_signature(), key_str, CHECK);
|
||||
|
||||
oop value_oop = result.get_oop();
|
||||
assert(value_oop != nullptr, "property must have a value");
|
||||
|
||||
// convert Java String to utf8 string
|
||||
char *system_value = java_lang_String::as_utf8_string(value_oop);
|
||||
|
||||
assert(strcmp(value, system_value) == 0, "property value mustn't differ from System.getProperty. Our value is: %s, System.getProperty is: %s",
|
||||
value, system_value);
|
||||
#endif // ASSERT
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a constant counter of the given property. Asserts the value does not
|
||||
* differ from the value retrievable from System.getProperty(name)
|
||||
*/
|
||||
void PerfDataManager::add_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS) {
|
||||
// the property must exist
|
||||
assert(value != nullptr, "property name should be have a value: %s", name);
|
||||
assert_system_property(name, value, CHECK);
|
||||
|
||||
// create the property counter
|
||||
PerfDataManager::create_string_constant(name_space, name, value, CHECK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a string constant of the given property. Retrieves the value via
|
||||
* Arguments::get_property() and asserts the value for the does not differ from
|
||||
* the value retrievable from System.getProperty()
|
||||
*/
|
||||
void PerfDataManager::add_property_constant(CounterNS name_space, const char* name, TRAPS) {
|
||||
add_property_constant(name_space, name, Arguments::get_property(name), CHECK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a string constant of the given property. Retrieves the value via
|
||||
* Arguments::get_property() and asserts the value for the does not differ from
|
||||
* the value retrievable from System.getProperty()
|
||||
*/
|
||||
void PerfDataManager::add_optional_property_constant(CounterNS name_space, const char* name, TRAPS) {
|
||||
const char* value = Arguments::get_property(name);
|
||||
|
||||
if (value != nullptr) {
|
||||
add_property_constant(name_space, name, value, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
add_item(p, true);
|
||||
void PerfDataManager::create_system_property_instrumentation(TRAPS) {
|
||||
|
||||
return p;
|
||||
// Non-writeable, constant properties
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.specification.name", "Java Virtual Machine Specification", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.version", JDK_Version::java_version(), CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.version", VM_Version::vm_release(), CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.name", VM_Version::vm_name(), CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.vendor", VM_Version::vm_vendor(), CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "jdk.debug", VM_Version::jdk_debug_level(), CHECK);
|
||||
|
||||
// Get remaining property constants via Arguments::get_property,
|
||||
// which does a linear search over the internal system properties list.
|
||||
|
||||
// SUN_PROPERTY properties
|
||||
add_property_constant(SUN_PROPERTY, "sun.boot.library.path", CHECK);
|
||||
|
||||
// JAVA_PROPERTY properties
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.specification.version", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.specification.vendor", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.info", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.library.path", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.class.path", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.home", CHECK);
|
||||
|
||||
add_optional_property_constant(JAVA_PROPERTY, "jdk.module.path", CHECK);
|
||||
add_optional_property_constant(JAVA_PROPERTY, "jdk.module.upgrade.path", CHECK);
|
||||
add_optional_property_constant(JAVA_PROPERTY, "jdk.module.main", CHECK);
|
||||
}
|
||||
|
||||
void PerfDataManager::create_misc_perfdata() {
|
||||
|
||||
ResourceMark rm;
|
||||
EXCEPTION_MARK;
|
||||
|
||||
// numeric constants
|
||||
|
||||
// frequency of the native high resolution timer
|
||||
create_constant(SUN_OS, "hrt.frequency", PerfData::U_Hertz,
|
||||
os::elapsed_frequency(), CHECK);
|
||||
|
||||
// string constants
|
||||
|
||||
// create string instrumentation for various Java properties.
|
||||
create_system_property_instrumentation(CHECK);
|
||||
|
||||
// HotSpot flags (from .hotspotrc) and args (from command line)
|
||||
//
|
||||
create_string_constant(JAVA_RT, "vmFlags", Arguments::jvm_flags(), CHECK);
|
||||
create_string_constant(JAVA_RT, "vmArgs", Arguments::jvm_args(), CHECK);
|
||||
|
||||
// java class name/jar file and arguments to main class
|
||||
// note: name is coordinated with launcher and Arguments.cpp
|
||||
create_string_constant(SUN_RT, "javaCommand", Arguments::java_command(), CHECK);
|
||||
|
||||
// the Java VM Internal version string
|
||||
create_string_constant(SUN_RT, "internalVersion",
|
||||
VM_Version::internal_vm_info_string(), CHECK);
|
||||
}
|
||||
|
||||
PerfDataList::PerfDataList(int length) {
|
||||
|
||||
@ -200,43 +200,10 @@ enum CounterNS {
|
||||
* are not encouraged to access the string constant's value via this
|
||||
* pointer at this time due to security concerns.
|
||||
*
|
||||
* Creating a performance counter in an arbitrary name space that holds a
|
||||
* value that is sampled by the StatSampler periodic task.
|
||||
*
|
||||
* PerfDataManager::create_counter("foo.sampled", PerfData::U_Events,
|
||||
* &my_jlong, CHECK);
|
||||
*
|
||||
* In this example, the PerfData pointer can be ignored as the caller
|
||||
* is relying on the StatSampler PeriodicTask to sample the given
|
||||
* address at a regular interval. The interval is defined by the
|
||||
* PerfDataSamplingInterval global variable, and is applied on
|
||||
* a system wide basis, not on an per-counter basis.
|
||||
*
|
||||
* Creating a performance counter in an arbitrary name space that utilizes
|
||||
* a helper object to return a value to the StatSampler via the take_sample()
|
||||
* method.
|
||||
*
|
||||
* class MyTimeSampler : public PerfLongSampleHelper {
|
||||
* public:
|
||||
* jlong take_sample() { return os::elapsed_counter(); }
|
||||
* };
|
||||
*
|
||||
* PerfDataManager::create_counter(SUN_RT, "helped",
|
||||
* PerfData::U_Ticks,
|
||||
* new MyTimeSampler(), CHECK);
|
||||
*
|
||||
* In this example, a subtype of PerfLongSampleHelper is instantiated
|
||||
* and its take_sample() method is overridden to perform whatever
|
||||
* operation is necessary to generate the data sample. This method
|
||||
* will be called by the StatSampler at a regular interval, defined
|
||||
* by the PerfDataSamplingInterval global variable.
|
||||
*
|
||||
* As before, PerfSampleHelper is an alias for PerfLongSampleHelper.
|
||||
*
|
||||
* For additional uses of PerfData subtypes, see the utility classes
|
||||
* PerfTraceTime and PerfTraceTimedEvent below.
|
||||
*
|
||||
* Always-on non-sampled counters can be created independent of
|
||||
* Always-on counters can be created independent of
|
||||
* the UsePerfData flag. Counters will be created on the c-heap
|
||||
* if UsePerfData is false.
|
||||
*
|
||||
@ -260,7 +227,6 @@ enum CounterNS {
|
||||
*/
|
||||
class PerfData : public CHeapObj<mtInternal> {
|
||||
|
||||
friend class StatSampler; // for access to protected void sample()
|
||||
friend class PerfDataManager; // for access to protected destructor
|
||||
friend class VMStructs;
|
||||
|
||||
@ -314,10 +280,6 @@ class PerfData : public CHeapObj<mtInternal> {
|
||||
// facilitate its use by external processes.
|
||||
void create_entry(BasicType dtype, size_t dsize, size_t dlen = 0);
|
||||
|
||||
// sample the data item given at creation time and write its value
|
||||
// into the its corresponding PerfMemory location.
|
||||
virtual void sample() = 0;
|
||||
|
||||
public:
|
||||
|
||||
// returns a boolean indicating the validity of this object.
|
||||
@ -352,17 +314,6 @@ class PerfData : public CHeapObj<mtInternal> {
|
||||
inline void* get_address() { return _valuep; }
|
||||
};
|
||||
|
||||
/*
|
||||
* PerfLongSampleHelper, and its alias PerfSamplerHelper, is a base class
|
||||
* for helper classes that rely upon the StatSampler periodic task to
|
||||
* invoke the take_sample() method and write the value returned to its
|
||||
* appropriate location in the PerfData memory region.
|
||||
*/
|
||||
class PerfLongSampleHelper : public CHeapObj<mtInternal> {
|
||||
public:
|
||||
virtual jlong take_sample() = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
* PerfLong is the base class for the various Long PerfData subtypes.
|
||||
* it contains implementation details that are common among its derived
|
||||
@ -390,10 +341,6 @@ class PerfLongConstant : public PerfLong {
|
||||
|
||||
friend class PerfDataManager; // for access to protected constructor
|
||||
|
||||
private:
|
||||
// hide sample() - no need to sample constants
|
||||
void sample() { }
|
||||
|
||||
protected:
|
||||
|
||||
PerfLongConstant(CounterNS ns, const char* namep, Units u,
|
||||
@ -413,19 +360,12 @@ class PerfLongConstant : public PerfLong {
|
||||
class PerfLongVariant : public PerfLong {
|
||||
|
||||
protected:
|
||||
PerfLongSampleHelper* _sample_helper;
|
||||
|
||||
PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
|
||||
jlong initial_value=0)
|
||||
: PerfLong(ns, namep, u, v) {
|
||||
if (is_valid()) *(jlong*)_valuep = initial_value;
|
||||
}
|
||||
|
||||
PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
|
||||
PerfLongSampleHelper* sample_helper);
|
||||
|
||||
void sample();
|
||||
|
||||
public:
|
||||
inline void inc() { (*(jlong*)_valuep)++; }
|
||||
inline void inc(jlong val) { (*(jlong*)_valuep) += val; }
|
||||
@ -451,11 +391,6 @@ class PerfLongCounter : public PerfLongVariant {
|
||||
jlong initial_value=0)
|
||||
: PerfLongVariant(ns, namep, u, V_Monotonic,
|
||||
initial_value) { }
|
||||
|
||||
PerfLongCounter(CounterNS ns, const char* namep, Units u,
|
||||
PerfLongSampleHelper* sample_helper)
|
||||
: PerfLongVariant(ns, namep, u, V_Monotonic,
|
||||
sample_helper) { }
|
||||
};
|
||||
|
||||
/*
|
||||
@ -474,11 +409,6 @@ class PerfLongVariable : public PerfLongVariant {
|
||||
: PerfLongVariant(ns, namep, u, V_Variable,
|
||||
initial_value) { }
|
||||
|
||||
PerfLongVariable(CounterNS ns, const char* namep, Units u,
|
||||
PerfLongSampleHelper* sample_helper)
|
||||
: PerfLongVariant(ns, namep, u, V_Variable,
|
||||
sample_helper) { }
|
||||
|
||||
public:
|
||||
inline void set_value(jlong val) { (*(jlong*)_valuep) = val; }
|
||||
};
|
||||
@ -521,11 +451,6 @@ class PerfStringConstant : public PerfString {
|
||||
|
||||
friend class PerfDataManager; // for access to protected constructor
|
||||
|
||||
private:
|
||||
|
||||
// hide sample() - no need to sample constants
|
||||
void sample() { }
|
||||
|
||||
protected:
|
||||
|
||||
// Restrict string constant lengths to be <= PerfMaxStringConstLength.
|
||||
@ -550,9 +475,6 @@ class PerfStringVariable : public PerfString {
|
||||
|
||||
protected:
|
||||
|
||||
// sampling of string variables are not yet supported
|
||||
void sample() { }
|
||||
|
||||
PerfStringVariable(CounterNS ns, const char* namep, jint max_length,
|
||||
const char* initial_value)
|
||||
: PerfString(ns, namep, V_Variable, max_length+1,
|
||||
@ -643,26 +565,23 @@ class PerfDataList : public CHeapObj<mtInternal> {
|
||||
* of the various PerfData types.
|
||||
*/
|
||||
class PerfDataManager : AllStatic {
|
||||
|
||||
friend class StatSampler; // for access to protected PerfDataList methods
|
||||
|
||||
private:
|
||||
static PerfDataList* _all;
|
||||
static PerfDataList* _sampled;
|
||||
static PerfDataList* _constants;
|
||||
static const char* _name_spaces[];
|
||||
static volatile bool _has_PerfData;
|
||||
|
||||
// add a PerfData item to the list(s) of know PerfData objects
|
||||
static void add_item(PerfData* p, bool sampled);
|
||||
|
||||
protected:
|
||||
|
||||
// return the list of all known PerfData items that are to be
|
||||
// sampled by the StatSampler.
|
||||
static PerfDataList* sampled();
|
||||
static void add_item(PerfData* p);
|
||||
|
||||
static void create_system_property_instrumentation(TRAPS);
|
||||
static void assert_system_property(const char* name, const char* value, TRAPS);
|
||||
static void add_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS);
|
||||
static void add_property_constant(CounterNS name_space, const char* name, TRAPS);
|
||||
static void add_optional_property_constant(CounterNS name_space, const char* name, TRAPS);
|
||||
public:
|
||||
// Creates miscellaneous perfdata constants
|
||||
static void create_misc_perfdata();
|
||||
|
||||
// method to check for the existence of a PerfData item with
|
||||
// the given name.
|
||||
@ -747,23 +666,12 @@ class PerfDataManager : AllStatic {
|
||||
return create_long_variable(ns, name, u, (jlong)0, THREAD);
|
||||
};
|
||||
|
||||
static PerfLongVariable* create_long_variable(CounterNS ns,
|
||||
const char* name,
|
||||
PerfData::Units u,
|
||||
PerfLongSampleHelper* sh,
|
||||
TRAPS);
|
||||
|
||||
|
||||
// Counter Types
|
||||
static PerfLongCounter* create_long_counter(CounterNS ns, const char* name,
|
||||
PerfData::Units u,
|
||||
jlong ival, TRAPS);
|
||||
|
||||
static PerfLongCounter* create_long_counter(CounterNS ns, const char* name,
|
||||
PerfData::Units u,
|
||||
PerfLongSampleHelper* sh,
|
||||
TRAPS);
|
||||
|
||||
|
||||
// these creation methods are provided for ease of use. These allow
|
||||
// Long performance data types to be created with a shorthand syntax.
|
||||
@ -783,23 +691,11 @@ class PerfDataManager : AllStatic {
|
||||
return create_long_variable(ns, name, u, (jlong)0, THREAD);
|
||||
}
|
||||
|
||||
static PerfVariable* create_variable(CounterNS ns, const char* name,
|
||||
PerfData::Units u,
|
||||
PerfSampleHelper* sh, TRAPS) {
|
||||
return create_long_variable(ns, name, u, sh, THREAD);
|
||||
}
|
||||
|
||||
static PerfCounter* create_counter(CounterNS ns, const char* name,
|
||||
PerfData::Units u, TRAPS) {
|
||||
return create_long_counter(ns, name, u, (jlong)0, THREAD);
|
||||
}
|
||||
|
||||
static PerfCounter* create_counter(CounterNS ns, const char* name,
|
||||
PerfData::Units u,
|
||||
PerfSampleHelper* sh, TRAPS) {
|
||||
return create_long_counter(ns, name, u, sh, THREAD);
|
||||
}
|
||||
|
||||
static void destroy();
|
||||
static bool has_PerfData() { return Atomic::load_acquire(&_has_PerfData); }
|
||||
};
|
||||
|
||||
@ -31,13 +31,11 @@
|
||||
// To reduce HotSpot build time, if you just need to declare a pointer to the
|
||||
// following types, include this file instead of perfData.hpp.
|
||||
|
||||
class PerfLongSampleHelper;
|
||||
class PerfLongConstant;
|
||||
class PerfLongCounter;
|
||||
class PerfLongVariable;
|
||||
class PerfStringVariable;
|
||||
|
||||
typedef PerfLongSampleHelper PerfSampleHelper;
|
||||
typedef PerfLongConstant PerfConstant;
|
||||
typedef PerfLongCounter PerfCounter;
|
||||
typedef PerfLongVariable PerfVariable;
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
#include "runtime/perfData.hpp"
|
||||
#include "runtime/perfMemory.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/statSampler.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
@ -66,16 +65,16 @@ void perfMemory_exit() {
|
||||
if (!UsePerfData) return;
|
||||
if (!PerfMemory::is_usable()) return;
|
||||
|
||||
// Only destroy PerfData objects if we're at a safepoint and the
|
||||
// StatSampler is not active. Otherwise, we risk removing PerfData
|
||||
// objects that are currently being used by running JavaThreads
|
||||
// or the StatSampler. This method is invoked while we are not at
|
||||
// Only destroy PerfData objects if we're at a safepoint.
|
||||
// Otherwise, we risk removing PerfData objects
|
||||
// that are currently being used by running JavaThreads.
|
||||
// This method is invoked while we are not at
|
||||
// a safepoint during a VM abort so leaving the PerfData objects
|
||||
// around may also help diagnose the failure. In rare cases,
|
||||
// PerfData objects are used in parallel with a safepoint. See
|
||||
// the work around in PerfDataManager::destroy().
|
||||
//
|
||||
if (SafepointSynchronize::is_at_safepoint() && !StatSampler::is_active()) {
|
||||
if (SafepointSynchronize::is_at_safepoint()) {
|
||||
PerfDataManager::destroy();
|
||||
}
|
||||
|
||||
|
||||
@ -1,349 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2025, 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 "classfile/javaClasses.hpp"
|
||||
#include "classfile/vmClasses.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/perfData.inline.hpp"
|
||||
#include "runtime/statSampler.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
|
||||
// --------------------------------------------------------
|
||||
// StatSamplerTask
|
||||
|
||||
class StatSamplerTask : public PeriodicTask {
|
||||
public:
|
||||
StatSamplerTask(int interval_time) : PeriodicTask(interval_time) {}
|
||||
void task() { StatSampler::collect_sample(); }
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Implementation of StatSampler
|
||||
|
||||
StatSamplerTask* StatSampler::_task = nullptr;
|
||||
PerfDataList* StatSampler::_sampled = nullptr;
|
||||
|
||||
/*
|
||||
* the initialize method is called from the engage() method
|
||||
* and is responsible for initializing various global variables.
|
||||
*/
|
||||
void StatSampler::initialize() {
|
||||
|
||||
if (!UsePerfData) return;
|
||||
|
||||
// create performance data that could not be created prior
|
||||
// to vm_init_globals() or otherwise have no logical home.
|
||||
|
||||
create_misc_perfdata();
|
||||
|
||||
// get copy of the sampled list
|
||||
_sampled = PerfDataManager::sampled();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* The engage() method is called at initialization time via
|
||||
* Thread::create_vm() to initialize the StatSampler and
|
||||
* register it with the WatcherThread as a periodic task.
|
||||
*/
|
||||
void StatSampler::engage() {
|
||||
|
||||
if (!UsePerfData) return;
|
||||
|
||||
if (!is_active()) {
|
||||
|
||||
initialize();
|
||||
|
||||
// start up the periodic task
|
||||
_task = new StatSamplerTask(PerfDataSamplingInterval);
|
||||
_task->enroll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* the disengage() method is responsible for deactivating the periodic
|
||||
* task and, if logging was enabled, for logging the final sample. This
|
||||
* method is called from before_exit() in java.cpp and is only called
|
||||
* after the WatcherThread has been stopped.
|
||||
*/
|
||||
void StatSampler::disengage() {
|
||||
|
||||
if (!UsePerfData) return;
|
||||
|
||||
if (!is_active())
|
||||
return;
|
||||
|
||||
// remove StatSamplerTask
|
||||
_task->disenroll();
|
||||
delete _task;
|
||||
_task = nullptr;
|
||||
|
||||
// force a final sample
|
||||
sample_data(_sampled);
|
||||
}
|
||||
|
||||
/*
|
||||
* the destroy method is responsible for releasing any resources used by
|
||||
* the StatSampler prior to shutdown of the VM. this method is called from
|
||||
* before_exit() in java.cpp and is only called after the WatcherThread
|
||||
* has stopped.
|
||||
*/
|
||||
void StatSampler::destroy() {
|
||||
|
||||
if (!UsePerfData) return;
|
||||
|
||||
if (_sampled != nullptr) {
|
||||
delete(_sampled);
|
||||
_sampled = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The sample_data() method is responsible for sampling the
|
||||
* the data value for each PerfData instance in the given list.
|
||||
*/
|
||||
void StatSampler::sample_data(PerfDataList* list) {
|
||||
|
||||
assert(list != nullptr, "null list unexpected");
|
||||
|
||||
for (int index = 0; index < list->length(); index++) {
|
||||
PerfData* item = list->at(index);
|
||||
item->sample();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* the collect_sample() method is the method invoked by the
|
||||
* WatcherThread via the PeriodicTask::task() method. This method
|
||||
* is responsible for collecting data samples from sampled
|
||||
* PerfData instances every PerfDataSamplingInterval milliseconds.
|
||||
* It is also responsible for logging the requested set of
|
||||
* PerfData instances every _sample_count milliseconds. While
|
||||
* logging data, it will output a column header after every _print_header
|
||||
* rows of data have been logged.
|
||||
*/
|
||||
void StatSampler::collect_sample() {
|
||||
|
||||
// future - check for new PerfData objects. PerfData objects might
|
||||
// get added to the PerfDataManager lists after we have already
|
||||
// built our local copies.
|
||||
//
|
||||
// if (PerfDataManager::count() > previous) {
|
||||
// // get a new copy of the sampled list
|
||||
// if (_sampled != nullptr) {
|
||||
// delete(_sampled);
|
||||
// _sampled = nullptr;
|
||||
// }
|
||||
// _sampled = PerfDataManager::sampled();
|
||||
// }
|
||||
|
||||
assert(_sampled != nullptr, "list not initialized");
|
||||
|
||||
sample_data(_sampled);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call into java.lang.System.getProperty to check that the value of the
|
||||
* specified property matches
|
||||
*/
|
||||
void StatSampler::assert_system_property(const char* name, const char* value, TRAPS) {
|
||||
#ifdef ASSERT
|
||||
ResourceMark rm(THREAD);
|
||||
|
||||
// setup the arguments to getProperty
|
||||
Handle key_str = java_lang_String::create_from_str(name, CHECK);
|
||||
|
||||
// return value
|
||||
JavaValue result(T_OBJECT);
|
||||
|
||||
// public static String getProperty(String key, String def);
|
||||
JavaCalls::call_static(&result,
|
||||
vmClasses::System_klass(),
|
||||
vmSymbols::getProperty_name(),
|
||||
vmSymbols::string_string_signature(),
|
||||
key_str,
|
||||
CHECK);
|
||||
|
||||
oop value_oop = result.get_oop();
|
||||
assert(value_oop != nullptr, "property must have a value");
|
||||
|
||||
// convert Java String to utf8 string
|
||||
char* system_value = java_lang_String::as_utf8_string(value_oop);
|
||||
|
||||
assert(strcmp(value, system_value) == 0, "property value mustn't differ from System.getProperty. Our value is: %s, System.getProperty is: %s",
|
||||
value, system_value);
|
||||
#endif // ASSERT
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a constant counter of the given property. Asserts the value does not
|
||||
* differ from the value retrievable from System.getProperty(name)
|
||||
*/
|
||||
void StatSampler::add_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS) {
|
||||
// the property must exist
|
||||
assert(value != nullptr, "property name should be have a value: %s", name);
|
||||
assert_system_property(name, value, CHECK);
|
||||
if (value != nullptr) {
|
||||
// create the property counter
|
||||
PerfDataManager::create_string_constant(name_space, name, value, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a string constant of the given property. Retrieves the value via
|
||||
* Arguments::get_property() and asserts the value for the does not differ from
|
||||
* the value retrievable from System.getProperty()
|
||||
*/
|
||||
void StatSampler::add_property_constant(CounterNS name_space, const char* name, TRAPS) {
|
||||
add_property_constant(name_space, name, Arguments::get_property(name), CHECK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a string constant of the given property. Retrieves the value via
|
||||
* Arguments::get_property() and asserts the value for the does not differ from
|
||||
* the value retrievable from System.getProperty()
|
||||
*/
|
||||
void StatSampler::add_optional_property_constant(CounterNS name_space, const char* name, TRAPS) {
|
||||
const char* value = Arguments::get_property(name);
|
||||
|
||||
if (value != nullptr) {
|
||||
add_property_constant(name_space, name, value, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to create PerfStringConstants containing the values of various
|
||||
* system properties. Constants are created from information known to HotSpot,
|
||||
* but are initialized as-if getting the values from System.getProperty()
|
||||
* during bootstrap.
|
||||
*
|
||||
* Property counters have a counter name space prefix prepended to the
|
||||
* property name.
|
||||
*/
|
||||
void StatSampler::create_system_property_instrumentation(TRAPS) {
|
||||
|
||||
// Non-writeable, constant properties
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.specification.name", "Java Virtual Machine Specification", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.version", JDK_Version::java_version(), CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.version", VM_Version::vm_release(), CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.name", VM_Version::vm_name(), CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.vendor", VM_Version::vm_vendor(), CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "jdk.debug", VM_Version::jdk_debug_level(), CHECK);
|
||||
|
||||
// Get remaining property constants via Arguments::get_property,
|
||||
// which does a linear search over the internal system properties list.
|
||||
|
||||
// SUN_PROPERTY properties
|
||||
add_property_constant(SUN_PROPERTY, "sun.boot.library.path", CHECK);
|
||||
|
||||
// JAVA_PROPERTY properties
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.specification.version", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.specification.vendor", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.vm.info", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.library.path", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.class.path", CHECK);
|
||||
add_property_constant(JAVA_PROPERTY, "java.home", CHECK);
|
||||
|
||||
add_optional_property_constant(JAVA_PROPERTY, "jdk.module.path", CHECK);
|
||||
add_optional_property_constant(JAVA_PROPERTY, "jdk.module.upgrade.path", CHECK);
|
||||
add_optional_property_constant(JAVA_PROPERTY, "jdk.module.main", CHECK);
|
||||
}
|
||||
|
||||
/*
|
||||
* The create_misc_perfdata() method provides a place to create
|
||||
* PerfData instances that would otherwise have no better place
|
||||
* to exist.
|
||||
*/
|
||||
void StatSampler::create_misc_perfdata() {
|
||||
|
||||
ResourceMark rm;
|
||||
EXCEPTION_MARK;
|
||||
|
||||
// numeric constants
|
||||
|
||||
// frequency of the native high resolution timer
|
||||
PerfDataManager::create_constant(SUN_OS, "hrt.frequency",
|
||||
PerfData::U_Hertz, os::elapsed_frequency(),
|
||||
CHECK);
|
||||
|
||||
// string constants
|
||||
|
||||
// create string instrumentation for various Java properties.
|
||||
create_system_property_instrumentation(CHECK);
|
||||
|
||||
// HotSpot flags (from .hotspotrc) and args (from command line)
|
||||
//
|
||||
PerfDataManager::create_string_constant(JAVA_RT, "vmFlags",
|
||||
Arguments::jvm_flags(), CHECK);
|
||||
PerfDataManager::create_string_constant(JAVA_RT, "vmArgs",
|
||||
Arguments::jvm_args(), CHECK);
|
||||
|
||||
// java class name/jar file and arguments to main class
|
||||
// note: name is coordinated with launcher and Arguments.cpp
|
||||
PerfDataManager::create_string_constant(SUN_RT, "javaCommand",
|
||||
Arguments::java_command(), CHECK);
|
||||
|
||||
// the Java VM Internal version string
|
||||
PerfDataManager::create_string_constant(SUN_RT, "internalVersion",
|
||||
VM_Version::internal_vm_info_string(),
|
||||
CHECK);
|
||||
|
||||
// create sampled instrumentation objects
|
||||
create_sampled_perfdata();
|
||||
}
|
||||
|
||||
/*
|
||||
* helper class to provide for sampling of the elapsed_counter value
|
||||
* maintained in the OS class.
|
||||
*/
|
||||
class HighResTimeSampler : public PerfSampleHelper {
|
||||
public:
|
||||
jlong take_sample() { return os::elapsed_counter(); }
|
||||
};
|
||||
|
||||
/*
|
||||
* the create_sampled_perdata() method provides a place to instantiate
|
||||
* sampled PerfData instances that would otherwise have no better place
|
||||
* to exist.
|
||||
*/
|
||||
void StatSampler::create_sampled_perfdata() {
|
||||
|
||||
EXCEPTION_MARK;
|
||||
|
||||
// setup sampling of the elapsed time counter maintained in the
|
||||
// the os class. This counter can be used as either a time stamp
|
||||
// for each logged entry or as a liveness indicator for the VM.
|
||||
PerfSampleHelper* psh = new HighResTimeSampler();
|
||||
PerfDataManager::create_counter(SUN_OS, "hrt.ticks",
|
||||
PerfData::U_Ticks, psh, CHECK);
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2024, 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_RUNTIME_STATSAMPLER_HPP
|
||||
#define SHARE_RUNTIME_STATSAMPLER_HPP
|
||||
|
||||
#include "runtime/perfData.hpp"
|
||||
#include "runtime/task.hpp"
|
||||
|
||||
class StatSamplerTask;
|
||||
|
||||
/*
|
||||
* The StatSampler class is responsible for periodically updating
|
||||
* sampled PerfData instances and writing the sampled values to the
|
||||
* PerfData memory region.
|
||||
*
|
||||
* In addition it is also responsible for providing a home for
|
||||
* PerfData instances that otherwise have no better home.
|
||||
*/
|
||||
class StatSampler : AllStatic {
|
||||
|
||||
friend class StatSamplerTask;
|
||||
|
||||
private:
|
||||
|
||||
static StatSamplerTask* _task;
|
||||
static PerfDataList* _sampled;
|
||||
|
||||
static void collect_sample();
|
||||
static void create_misc_perfdata();
|
||||
static void create_sampled_perfdata();
|
||||
static void sample_data(PerfDataList* list);
|
||||
static void assert_system_property(const char* name, const char* value, TRAPS);
|
||||
static void add_property_constant(CounterNS name_space, const char* name, TRAPS);
|
||||
static void add_optional_property_constant(CounterNS name_space, const char* name, TRAPS);
|
||||
static void add_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS);
|
||||
static void create_system_property_instrumentation(TRAPS);
|
||||
|
||||
public:
|
||||
// Start/stop the sampler
|
||||
static void engage();
|
||||
static void disengage();
|
||||
|
||||
static bool is_active() { return _task != nullptr; }
|
||||
|
||||
static void initialize();
|
||||
static void destroy();
|
||||
};
|
||||
|
||||
#endif // SHARE_RUNTIME_STATSAMPLER_HPP
|
||||
@ -82,13 +82,13 @@
|
||||
#include "runtime/nonJavaThread.hpp"
|
||||
#include "runtime/objectMonitor.inline.hpp"
|
||||
#include "runtime/osThread.hpp"
|
||||
#include "runtime/perfData.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/safepointMechanism.inline.hpp"
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
#include "runtime/serviceThread.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stackWatermarkSet.inline.hpp"
|
||||
#include "runtime/statSampler.hpp"
|
||||
#include "runtime/stubCodeGenerator.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
#include "runtime/threadSMR.inline.hpp"
|
||||
@ -852,7 +852,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||
}
|
||||
#endif // INCLUDE_MANAGEMENT
|
||||
|
||||
StatSampler::engage();
|
||||
if (UsePerfData) PerfDataManager::create_misc_perfdata();
|
||||
if (CheckJNICalls) JniPeriodicChecker::engage();
|
||||
|
||||
call_postVMInitHook(THREAD);
|
||||
@ -906,7 +906,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||
// + Call before_exit(), prepare for VM exit
|
||||
// > run VM level shutdown hooks (they are registered through JVM_OnExit(),
|
||||
// currently the only user of this mechanism is File.deleteOnExit())
|
||||
// > stop StatSampler, watcher thread,
|
||||
// > stop watcher thread,
|
||||
// post thread end and vm death events to JVMTI,
|
||||
// stop signal thread
|
||||
// + Call JavaThread::exit(), it will:
|
||||
|
||||
@ -244,11 +244,9 @@ public class PerfDataBuffer extends PerfDataBufferImpl {
|
||||
* Method to provide a gross level of synchronization with the
|
||||
* target monitored jvm.
|
||||
*
|
||||
* gross synchronization works by polling for the hotspot.rt.hrt.ticks
|
||||
* counter, which is the last counter created by the StatSampler
|
||||
* initialization code. The counter is updated when the watcher thread
|
||||
* starts scheduling tasks, which is the last thing done in vm
|
||||
* initialization.
|
||||
* gross synchronization works by polling for the hotspot.rt.hrt.frequency
|
||||
* constant, which is created by the PerfData initialization code. The
|
||||
* creation of constants is one of the last things done in vm initialization.
|
||||
*/
|
||||
protected void synchWithTarget(Map<String, Monitor> map) throws MonitorException {
|
||||
/*
|
||||
@ -258,7 +256,7 @@ public class PerfDataBuffer extends PerfDataBufferImpl {
|
||||
*/
|
||||
long timeLimit = System.currentTimeMillis() + syncWaitMs;
|
||||
|
||||
String name = "hotspot.rt.hrt.ticks";
|
||||
String name = "hotspot.rt.hrt.frequency";
|
||||
LongMonitor ticks = (LongMonitor)pollFor(map, name, timeLimit);
|
||||
|
||||
/*
|
||||
|
||||
@ -541,8 +541,6 @@ alias sun.gc.tlab.refillWaste // 17
|
||||
// sun.os
|
||||
alias sun.os.hrt.frequency // 1.5.0 b39
|
||||
hotspot.rt.hrt.frequency // 1.4.1
|
||||
alias sun.os.hrt.ticks // 1.5.0 b39
|
||||
hotspot.rt.hrt.ticks // 1.4.1
|
||||
|
||||
// sun.perfdata
|
||||
alias sun.perfdata.overflow // 1.5.0 b39
|
||||
|
||||
@ -61,6 +61,10 @@ public class ExpressionExecuter implements ExpressionEvaluator {
|
||||
return ((Literal)e).getValue();
|
||||
}
|
||||
|
||||
if (e instanceof Timestamp) {
|
||||
return ((Timestamp)e).getValue();
|
||||
}
|
||||
|
||||
if (e instanceof Identifier) {
|
||||
Identifier id = (Identifier)e;
|
||||
if (map.containsKey(id.getName())) {
|
||||
|
||||
@ -87,7 +87,7 @@ public class ExpressionResolver implements ExpressionEvaluator {
|
||||
return id;
|
||||
}
|
||||
|
||||
if (e instanceof Literal) {
|
||||
if (e instanceof Literal || e instanceof Timestamp) {
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
@ -222,6 +222,13 @@ public class Parser {
|
||||
return reservedWords.contains(word);
|
||||
}
|
||||
|
||||
/**
|
||||
* determine if the given word is the timestamp key word
|
||||
*/
|
||||
private boolean isTimestamp(String word) {
|
||||
return word.equals("jstat.timestamp");
|
||||
}
|
||||
|
||||
/**
|
||||
* determine if the give work is a reserved key word
|
||||
*/
|
||||
@ -297,7 +304,7 @@ public class Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary -> Literal | Identifier | '(' Expression ')'
|
||||
* Primary -> Literal | Timestamp | Identifier | '(' Expression ')'
|
||||
*/
|
||||
private Expression primary() throws ParserException, IOException {
|
||||
Expression e = null;
|
||||
@ -315,7 +322,7 @@ public class Parser {
|
||||
"Reserved Word: " + lookahead.sval);
|
||||
}
|
||||
matchID();
|
||||
e = new Identifier(s);
|
||||
e = isTimestamp(s) ? new Timestamp() : new Identifier(s);
|
||||
log(pdebug, "Parsed: ID -> " + s);
|
||||
break;
|
||||
case StreamTokenizer.TT_NUMBER:
|
||||
|
||||
41
src/jdk.jcmd/share/classes/sun/tools/jstat/Timestamp.java
Normal file
41
src/jdk.jcmd/share/classes/sun/tools/jstat/Timestamp.java
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2025, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package sun.tools.jstat;
|
||||
|
||||
public class Timestamp extends Expression {
|
||||
|
||||
public Timestamp() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "jstat.timestamp";
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,7 @@
|
||||
option timestamp {
|
||||
column {
|
||||
header "^Timestamp"
|
||||
data (sun.os.hrt.ticks/sun.os.hrt.frequency)
|
||||
data ((jstat.timestamp - sun.rt.createVmBeginTime) / 1000)
|
||||
scale sec
|
||||
align right
|
||||
width 15
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user