8255231: Avoid upcalls when initializing the statSampler

Reviewed-by: iklam, dholmes
This commit is contained in:
Claes Redestad 2020-10-27 10:31:21 +00:00
parent dccfd2b3e0
commit f7c59c661c
7 changed files with 93 additions and 83 deletions
src

@ -147,6 +147,7 @@
\
/* Java runtime version access */ \
template(java_lang_VersionProps, "java/lang/VersionProps") \
template(java_version_name, "java_version") \
template(java_runtime_name_name, "java_runtime_name") \
template(java_runtime_version_name, "java_runtime_version") \
template(java_runtime_vendor_version_name, "VENDOR_VERSION") \

@ -688,6 +688,7 @@ void vm_shutdown_during_initialization(const char* error, const char* message) {
}
JDK_Version JDK_Version::_current;
const char* JDK_Version::_java_version;
const char* JDK_Version::_runtime_name;
const char* JDK_Version::_runtime_version;
const char* JDK_Version::_runtime_vendor_version;

@ -65,6 +65,7 @@ class JDK_Version {
private:
static JDK_Version _current;
static const char* _java_version;
static const char* _runtime_name;
static const char* _runtime_version;
static const char* _runtime_vendor_version;
@ -130,6 +131,13 @@ class JDK_Version {
void to_string(char* buffer, size_t buflen) const;
static const char* java_version() {
return _java_version;
}
static void set_java_version(const char* version) {
_java_version = version;
}
static const char* runtime_name() {
return _runtime_name;
}

@ -173,15 +173,15 @@ void StatSampler::collect_sample() {
}
/*
* method to upcall into Java to return the value of the specified
* property as a utf8 string, or NULL if does not exist. The caller
* is responsible for setting a ResourceMark for proper cleanup of
* the utf8 strings.
* Call into java.lang.System.getProperty to check that the value of the
* specified property matches
*/
const char* StatSampler::get_system_property(const char* name, TRAPS) {
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_NULL);
Handle key_str = java_lang_String::create_from_str(name, CHECK);
// return value
JavaValue result(T_OBJECT);
@ -192,100 +192,73 @@ const char* StatSampler::get_system_property(const char* name, TRAPS) {
vmSymbols::getProperty_name(),
vmSymbols::string_string_signature(),
key_str,
CHECK_NULL);
CHECK);
oop value_oop = (oop)result.get_jobject();
if (value_oop == NULL) {
return NULL;
}
assert(value_oop != NULL, "property must have a value");
// convert Java String to utf8 string
char* value = java_lang_String::as_utf8_string(value_oop);
char* system_value = java_lang_String::as_utf8_string(value_oop);
return value;
assert(strcmp(value, system_value) == 0, "property value mustn't differ from System.getProperty");
#endif // ASSERT
}
/*
* The list of System Properties that have corresponding PerfData
* string instrumentation created by retrieving the named property's
* value from System.getProperty() and unconditionally creating a
* PerfStringConstant object initialized to the retrieved value. This
* is not an exhaustive list of Java properties with corresponding string
* instrumentation as the create_system_property_instrumentation() method
* creates other property based instrumentation conditionally.
* Adds a constant counter of the given property. Asserts the value does not
* differ from the value retrievable from System.getProperty(name)
*/
// stable interface, supported counters
static const char* property_counters_ss[] = {
"java.vm.specification.version",
"java.vm.specification.name",
"java.vm.specification.vendor",
"java.vm.version",
"java.vm.name",
"java.vm.vendor",
"java.vm.info",
"jdk.debug",
"java.library.path",
"java.class.path",
"java.version",
"java.home",
NULL
};
// unstable interface, supported counters
static const char* property_counters_us[] = {
NULL
};
// unstable interface, unsupported counters
static const char* property_counters_uu[] = {
"sun.boot.library.path",
NULL
};
typedef struct {
const char** property_list;
CounterNS name_space;
} PropertyCounters;
static PropertyCounters property_counters[] = {
{ property_counters_ss, JAVA_PROPERTY },
{ property_counters_us, COM_PROPERTY },
{ property_counters_uu, SUN_PROPERTY },
{ NULL, SUN_PROPERTY }
};
void StatSampler::add_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS) {
// the property must exist
assert(value != NULL, "property name should be have a value: %s", name);
assert_system_property(name, value, CHECK);
if (value != NULL) {
// create the property counter
PerfDataManager::create_string_constant(name_space, name, value, CHECK);
}
}
/*
* Method to create PerfData string instruments that contain the values
* of various system properties. String instruments are created for each
* property specified in the property lists provided in property_counters[].
* 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);
}
/*
* 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 as indicated in property_counters[].
* property name.
*/
void StatSampler::create_system_property_instrumentation(TRAPS) {
ResourceMark rm;
// 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);
for (int i = 0; property_counters[i].property_list != NULL; i++) {
// Get remaining property constants via Arguments::get_property,
// which does a linear search over the internal system properties list.
for (int j = 0; property_counters[i].property_list[j] != NULL; j++) {
// SUN_PROPERTY properties
add_property_constant(SUN_PROPERTY, "sun.boot.library.path", CHECK);
const char* property_name = property_counters[i].property_list[j];
assert(property_name != NULL, "property name should not be NULL");
const char* value = get_system_property(property_name, CHECK);
// the property must exist
assert(value != NULL, "property name should be valid");
if (value != NULL) {
// create the property counter
PerfDataManager::create_string_constant(property_counters[i].name_space,
property_name, value, 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);
}
/*

@ -51,7 +51,9 @@ class StatSampler : AllStatic {
static void create_misc_perfdata();
static void create_sampled_perfdata();
static void sample_data(PerfDataList* list);
static const char* get_system_property(const char* name, TRAPS);
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_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS);
static void create_system_property_instrumentation(TRAPS);
public:

@ -894,11 +894,34 @@ static void create_initial_thread(Handle thread_group, JavaThread* thread,
java_lang_Thread::RUNNABLE);
}
char java_version[64] = "";
char java_runtime_name[128] = "";
char java_runtime_version[128] = "";
char java_runtime_vendor_version[128] = "";
char java_runtime_vendor_vm_bug_url[128] = "";
// extract the JRE version string from java.lang.VersionProps.java_version
static const char* get_java_version(TRAPS) {
Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(),
Handle(), Handle(), CHECK_AND_CLEAR_NULL);
fieldDescriptor fd;
bool found = k != NULL &&
InstanceKlass::cast(k)->find_local_field(vmSymbols::java_version_name(),
vmSymbols::string_signature(), &fd);
if (found) {
oop name_oop = k->java_mirror()->obj_field(fd.offset());
if (name_oop == NULL) {
return NULL;
}
const char* name = java_lang_String::as_utf8_string(name_oop,
java_version,
sizeof(java_version));
return name;
} else {
return NULL;
}
}
// extract the JRE name from java.lang.VersionProps.java_runtime_name
static const char* get_java_runtime_name(TRAPS) {
Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(),
@ -3383,6 +3406,7 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
call_initPhase1(CHECK);
// get the Java runtime name, version, and vendor info after java.lang.System is initialized
JDK_Version::set_java_version(get_java_version(THREAD));
JDK_Version::set_runtime_name(get_java_runtime_name(THREAD));
JDK_Version::set_runtime_version(get_java_runtime_version(THREAD));
JDK_Version::set_runtime_vendor_version(get_java_runtime_vendor_version(THREAD));

@ -36,6 +36,7 @@ class VersionProps {
private static final String launcher_name =
"@@LAUNCHER_NAME@@";
// This field is read by HotSpot
private static final String java_version =
"@@VERSION_SHORT@@";