diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 4937456d09f25..764d22df68e9f 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -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" diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index e517e8f30a0ca..b7eae978154a3 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -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" diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 1b48550bfb794..807014e7b0cb4 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -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" diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index b67717194278f..ed7cd18881e23 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -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" diff --git a/src/hotspot/share/gc/parallel/spaceCounters.cpp b/src/hotspot/share/gc/parallel/spaceCounters.cpp index 4133fc2e2480a..c15d25dc0aab7 100644 --- a/src/hotspot/share/gc/parallel/spaceCounters.cpp +++ b/src/hotspot/share/gc/parallel/spaceCounters.cpp @@ -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()); } diff --git a/src/hotspot/share/gc/parallel/spaceCounters.hpp b/src/hotspot/share/gc/parallel/spaceCounters.hpp index 3d0c1ff7b5015..b33aac386a680 100644 --- a/src/hotspot/share/gc/parallel/spaceCounters.hpp +++ b/src/hotspot/share/gc/parallel/spaceCounters.hpp @@ -39,7 +39,6 @@ class SpaceCounters: public CHeapObj { 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 { 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 { 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 diff --git a/src/hotspot/share/gc/serial/cSpaceCounters.cpp b/src/hotspot/share/gc/serial/cSpaceCounters.cpp index 9f8b91e205cd0..f6bcee99423c4 100644 --- a/src/hotspot/share/gc/serial/cSpaceCounters.cpp +++ b/src/hotspot/share/gc/serial/cSpaceCounters.cpp @@ -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); -} diff --git a/src/hotspot/share/gc/serial/cSpaceCounters.hpp b/src/hotspot/share/gc/serial/cSpaceCounters.hpp index 334f649382bfe..b378f379afe9f 100644 --- a/src/hotspot/share/gc/serial/cSpaceCounters.hpp +++ b/src/hotspot/share/gc/serial/cSpaceCounters.hpp @@ -39,7 +39,6 @@ class CSpaceCounters: public CHeapObj { 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 { 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 { 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 diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 8b1f5e645d44e..62fcc65743aed 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -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() }, diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 2b07f9d47e177..290ce0d3cba2d 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -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") \ \ diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index 1079212a843e5..8b6eee116a114 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -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 diff --git a/src/hotspot/share/runtime/perfData.cpp b/src/hotspot/share/runtime/perfData.cpp index ba6370e596a51..bc9d86400dcf5 100644 --- a/src/hotspot/share/runtime/perfData.cpp +++ b/src/hotspot/share/runtime/perfData.cpp @@ -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,21 +388,17 @@ PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); } - add_item(p, false); + add_item(p); 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; +PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, + const char* name, + PerfData::Units u, + jlong ival, TRAPS) { - PerfLongVariable* p = new PerfLongVariable(ns, name, u, sh); + PerfLongCounter* p = new PerfLongCounter(ns, name, u, ival); if (!p->is_valid()) { // allocation of native resources failed. @@ -443,49 +406,133 @@ PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); } - add_item(p, true); + add_item(p); return p; } -PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, - const char* name, - PerfData::Units u, - jlong ival, 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); - PerfLongCounter* p = new PerfLongCounter(ns, name, u, ival); + // setup the arguments to getProperty + Handle key_str = java_lang_String::create_from_str(name, CHECK); - if (!p->is_valid()) { - // allocation of native resources failed. - delete p; - THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); - } + // return value + JavaValue result(T_OBJECT); - add_item(p, false); + // 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); - return p; + 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 } -PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, - const char* name, - PerfData::Units u, - PerfSampleHelper* sh, - TRAPS) { +/* + * 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); - // Sampled counters not supported if UsePerfData is false - if (!UsePerfData) return nullptr; + // create the property counter + PerfDataManager::create_string_constant(name_space, name, value, CHECK); +} - PerfLongCounter* p = new PerfLongCounter(ns, name, u, sh); +/* + * 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); +} - if (!p->is_valid()) { - // allocation of native resources failed. - delete p; - THROW_NULL(vmSymbols::java_lang_OutOfMemoryError()); +/* + * 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); } +} + +void PerfDataManager::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); +} - add_item(p, true); +void PerfDataManager::create_misc_perfdata() { - return p; + 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) { diff --git a/src/hotspot/share/runtime/perfData.hpp b/src/hotspot/share/runtime/perfData.hpp index c14bc40c10a21..7f05e4673fce5 100644 --- a/src/hotspot/share/runtime/perfData.hpp +++ b/src/hotspot/share/runtime/perfData.hpp @@ -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 { - 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 { // 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 { 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 { - 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 { * 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); } }; diff --git a/src/hotspot/share/runtime/perfDataTypes.hpp b/src/hotspot/share/runtime/perfDataTypes.hpp index e619ef78a5f93..9928975b8e296 100644 --- a/src/hotspot/share/runtime/perfDataTypes.hpp +++ b/src/hotspot/share/runtime/perfDataTypes.hpp @@ -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; diff --git a/src/hotspot/share/runtime/perfMemory.cpp b/src/hotspot/share/runtime/perfMemory.cpp index 5b44c56261d64..1122aa8da471d 100644 --- a/src/hotspot/share/runtime/perfMemory.cpp +++ b/src/hotspot/share/runtime/perfMemory.cpp @@ -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(); } diff --git a/src/hotspot/share/runtime/statSampler.cpp b/src/hotspot/share/runtime/statSampler.cpp deleted file mode 100644 index acae27944b037..0000000000000 --- a/src/hotspot/share/runtime/statSampler.cpp +++ /dev/null @@ -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); -} diff --git a/src/hotspot/share/runtime/statSampler.hpp b/src/hotspot/share/runtime/statSampler.hpp deleted file mode 100644 index b42700caffa26..0000000000000 --- a/src/hotspot/share/runtime/statSampler.hpp +++ /dev/null @@ -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 diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 47c030fdb729e..67f452794099e 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -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: diff --git a/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v1_0/PerfDataBuffer.java b/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v1_0/PerfDataBuffer.java index 35582943c3da6..ba02e792f3e7b 100644 --- a/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v1_0/PerfDataBuffer.java +++ b/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v1_0/PerfDataBuffer.java @@ -244,11 +244,9 @@ protected void buildPseudoMonitors(Map map) { * 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 map) throws MonitorException { /* @@ -258,7 +256,7 @@ protected void synchWithTarget(Map map) throws MonitorException */ long timeLimit = System.currentTimeMillis() + syncWaitMs; - String name = "hotspot.rt.hrt.ticks"; + String name = "hotspot.rt.hrt.frequency"; LongMonitor ticks = (LongMonitor)pollFor(map, name, timeLimit); /* diff --git a/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/resources/aliasmap b/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/resources/aliasmap index ecc752e8014a7..e19521c83a90c 100644 --- a/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/resources/aliasmap +++ b/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/resources/aliasmap @@ -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 diff --git a/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java b/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java index c49cdf55502b1..860fd83219743 100644 --- a/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java +++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java @@ -61,6 +61,10 @@ public Object evaluate(Expression e) { 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())) { diff --git a/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java b/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java index 98602df2207d0..f0e1bc371e3fd 100644 --- a/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java +++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java @@ -87,7 +87,7 @@ public Object evaluate(Expression e) throws MonitorException { return id; } - if (e instanceof Literal) { + if (e instanceof Literal || e instanceof Timestamp) { return e; } diff --git a/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java b/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java index da0827c185dc4..cf1790d65e6eb 100644 --- a/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java +++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java @@ -222,6 +222,13 @@ private boolean isReservedWord(String word) { 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 @@ private void formatStmt(ColumnFormat cf) } /** - * Primary -> Literal | Identifier | '(' Expression ')' + * Primary -> Literal | Timestamp | Identifier | '(' Expression ')' */ private Expression primary() throws ParserException, IOException { Expression e = null; @@ -315,7 +322,7 @@ private Expression primary() throws ParserException, IOException { "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: diff --git a/src/jdk.jcmd/share/classes/sun/tools/jstat/Timestamp.java b/src/jdk.jcmd/share/classes/sun/tools/jstat/Timestamp.java new file mode 100644 index 0000000000000..8d96fab5c0008 --- /dev/null +++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/Timestamp.java @@ -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"; + } +} diff --git a/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options b/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options index 7fe7487e11af9..6bf67b9bdc441 100644 --- a/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options +++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options @@ -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