8211230: JFR: internal events

Reviewed-by: mgronlun
This commit is contained in:
Erik Gahlin 2021-12-09 14:13:53 +00:00
parent 965ea8d9cd
commit 08aad8506e
20 changed files with 219 additions and 32 deletions

View File

@ -174,6 +174,7 @@ public class GenerateJfrFiles {
boolean cutoff;
boolean throttle;
boolean experimental;
boolean internal;
long id;
boolean isEvent;
boolean isRelation;
@ -197,6 +198,7 @@ public class GenerateJfrFiles {
pos.writeBoolean(cutoff);
pos.writeBoolean(throttle);
pos.writeBoolean(experimental);
pos.writeBoolean(internal);
pos.writeLong(id);
pos.writeBoolean(isEvent);
pos.writeBoolean(isRelation);
@ -487,6 +489,7 @@ public class GenerateJfrFiles {
currentType.description = getString(attributes, "description");
currentType.category = getString(attributes, "category");
currentType.experimental = getBoolean(attributes, "experimental", false);
currentType.internal = getBoolean(attributes, "internal", false);
currentType.thread = getBoolean(attributes, "thread", false);
currentType.stackTrace = getBoolean(attributes, "stackTrace", false);
currentType.startTime = getBoolean(attributes, "startTime", true);
@ -863,6 +866,9 @@ public class GenerateJfrFiles {
private static void printWriteData(Printer out, TypeElement type) {
out.write(" template <typename Writer>");
out.write(" void writeData(Writer& w) {");
if (type.isEvent && type.internal) {
out.write(" JfrEventSetting::unhide_internal_types();");
}
if (("_thread_in_native").equals(type.commitState)) {
out.write(" // explicit epoch synchronization check");
out.write(" JfrEpochSynchronization sync;");

View File

@ -32,6 +32,7 @@
#include "jfr/support/jfrJdkJfrEvent.hpp"
#include "logging/log.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayKlass.hpp"
#include "oops/typeArrayOop.inline.hpp"
@ -45,6 +46,8 @@ static Symbol* on_retransform_method_sym = NULL;
static Symbol* on_retransform_signature_sym = NULL;
static Symbol* bytes_for_eager_instrumentation_sym = NULL;
static Symbol* bytes_for_eager_instrumentation_sig_sym = NULL;
static Symbol* unhide_internal_types_sym = NULL;
static Symbol* unhide_internal_types_sig_sym = NULL;
static bool initialize(TRAPS) {
static bool initialized = false;
@ -55,7 +58,9 @@ static bool initialize(TRAPS) {
on_retransform_signature_sym = SymbolTable::new_permanent_symbol("(JZLjava/lang/Class;[B)[B");
bytes_for_eager_instrumentation_sym = SymbolTable::new_permanent_symbol("bytesForEagerInstrumentation");
bytes_for_eager_instrumentation_sig_sym = SymbolTable::new_permanent_symbol("(JZLjava/lang/Class;[B)[B");
initialized = bytes_for_eager_instrumentation_sig_sym != NULL;
unhide_internal_types_sym = SymbolTable::new_permanent_symbol("unhideInternalTypes");
unhide_internal_types_sig_sym = SymbolTable::new_permanent_symbol("()V");
initialized = unhide_internal_types_sig_sym != NULL;
}
return initialized;
}
@ -82,7 +87,8 @@ static const typeArrayOop invoke(jlong trace_id,
args.push_oop(old_byte_array);
JfrJavaSupport::call_static(&args, THREAD);
if (HAS_PENDING_EXCEPTION) {
log_error(jfr, system)("JfrUpcall failed");
ResourceMark rm(THREAD);
log_error(jfr, system)("JfrUpcall failed for %s", method_sym->as_C_string());
return NULL;
}
// The result should be a [B
@ -179,3 +185,19 @@ void JfrUpcalls::new_bytes_eager_instrumentation(jlong trace_id,
*new_class_data_len = new_bytes_length;
*new_class_data = new_bytes;
}
bool JfrUpcalls::unhide_internal_types(TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
JavaValue result(T_VOID);
const Klass* klass = SystemDictionary::resolve_or_fail(jvm_upcalls_class_sym, true, CHECK_false);
assert(klass != NULL, "invariant");
JfrJavaArguments args(&result, klass, unhide_internal_types_sym, unhide_internal_types_sig_sym);
JfrJavaSupport::call_static(&args, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
ResourceMark rm(THREAD);
log_error(jfr, system)("JfrUpcall failed for %s", unhide_internal_types_sym->as_C_string());
return false;
}
return true;
}

View File

@ -53,6 +53,8 @@ class JfrUpcalls : AllStatic {
jint* new_class_data_len,
unsigned char** new_class_data,
TRAPS);
static bool unhide_internal_types(TRAPS);
};
#endif // SHARE_JFR_JNI_JFRUPCALLS_HPP

View File

@ -26,6 +26,55 @@
<Metadata>
<!-- Internal events are only to be used during development, i.e. temporary time measurements, without the need
to modify .jfc files etc. Code that commits an internal event should NEVER be checked in.
Example usage:
#include "jfr/jfrEvents.hpp"
void foo() {
EventDuration event;
bar();
baz();
event.commit();
}
$ make images
$ java -XX:StartFlightRecording:settings=none,filename=dump.jfr ...
...
$ jfr print dump.jfr
Programmatic access:
try (var rf = new RecordingFile(Path.of("dump.jfr)) {
while (rf.hasMoreEvents()) {
RecordedEvent e = rf.readEvent();
System.out.println(e.getName() + " " + e.getDuration()));
}
};
!-->
<Event name="Duration" category="Java Virtual Machine, Internal" label="Duration" startTime="true" thread="true" stackTrace="false" internal="true">
</Event>
<Event name="Instant" category="Java Virtual Machine, Internal" label="Instant" startTime="false" thread="true" stackTrace="false" internal="true">
</Event>
<Event name="Value" category="Java Virtual Machine, Internal" label="Value" startTime="false" thread="true" stackTrace="false" internal="true">
<Field type="ulong" name="value" label="Value"/>
</Event>
<Event name="Text" category="Java Virtual Machine, Internal" label="Text" startTime="false" thread="true" stackTrace="false" internal="true">
<Field type="string" name="text" label="Text"/>
</Event>
<Event name="ZThreadDebug" category="Java Virtual Machine, GC, Detailed" label="ZGC Thread Event" description="Temporary latency measurements used during development and debugging of ZGC" thread="true" internal="true">
<Field type="uint" name="gcId" label="GC Identifier" relation="GcId"/>
<Field type="string" name="name" label="Name" />
</Event>
<!-- Ordinary and experimental events !-->
<Event name="ThreadStart" category="Java Application" label="Java Thread Start" thread="true" startTime="false" stackTrace="true">
<Field type="Thread" name="thread" label="New Java Thread" />
<Field type="Thread" name="parentThread" label="Parent Java Thread" />
@ -1034,11 +1083,6 @@
<Field type="string" name="name" label="Name" />
</Event>
<Event name="ZThreadDebug" category="Java Virtual Machine, GC, Detailed" label="ZGC Thread Event" description="Temporary latency measurements used during development and debugging of ZGC" thread="true" experimental="true">
<Field type="uint" name="gcId" label="GC Identifier" relation="GcId"/>
<Field type="string" name="name" label="Name" />
</Event>
<Event name="ZUncommit" category="Java Virtual Machine, GC, Detailed" label="ZGC Uncommit" description="Uncommitting of memory" thread="true">
<Field type="ulong" contentType="bytes" name="uncommitted" label="Uncommitted" />
</Event>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
@ -65,6 +65,7 @@
<xs:attribute name="label" type="xs:string" use="required" />
<xs:attribute name="description" type="xs:string" use="optional" />
<xs:attribute name="experimental" type="xs:boolean" use="optional" />
<xs:attribute name="internal" type="xs:boolean" use="optional" />
<xs:attribute name="thread" type="xs:boolean" use="optional" />
<xs:attribute name="startTime" type="xs:boolean" use="optional" />
<xs:attribute name="stackTrace" type="xs:boolean" use="optional" />
@ -87,6 +88,7 @@
<xs:attribute name="label" type="xs:string" use="required" />
<xs:attribute name="description" type="xs:string" use="optional" />
<xs:attribute name="experimental" type="xs:boolean" use="optional" />
<xs:attribute name="internal" type="xs:boolean" use="optional" />
<xs:attribute name="relation" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>

View File

@ -24,18 +24,32 @@
#include "precompiled.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/jni/jfrUpcalls.hpp"
#include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
#include "jfr/recorder/jfrEventSetting.inline.hpp"
#include "oops/klass.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/exceptions.hpp"
static jbyteArray metadata_blob = NULL;
static u8 metadata_id = 0;
static u8 last_metadata_id = 0;
static void check_internal_types() {
static bool visible = false;
if (!visible && JfrEventSetting::is_internal_types_visible()) {
JavaThread* const jt = JavaThread::current();
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
// can safepoint here
ThreadInVMfromNative transition(jt);
visible = JfrUpcalls::unhide_internal_types(jt);
}
}
static void write_metadata_blob(JfrChunkWriter& chunkwriter, JavaThread* thread) {
assert(chunkwriter.is_valid(), "invariant");
assert(thread != NULL, "invariant");
@ -53,6 +67,7 @@ static void write_metadata_blob(JfrChunkWriter& chunkwriter, JavaThread* thread)
void JfrMetadataEvent::write(JfrChunkWriter& chunkwriter) {
assert(chunkwriter.is_valid(), "invariant");
check_internal_types();
if (last_metadata_id == metadata_id && chunkwriter.has_metadata()) {
return;
}

View File

@ -26,6 +26,7 @@
#include "jfr/recorder/jfrEventSetting.inline.hpp"
JfrNativeSettings JfrEventSetting::_jvm_event_settings;
bool JfrEventSetting::_internal_types = false;
bool JfrEventSetting::set_threshold(jlong id, jlong threshold_ticks) {
JfrEventId event_id = (JfrEventId)id;
@ -58,6 +59,15 @@ void JfrEventSetting::set_large(JfrEventId event_id) {
setting(event_id).large = true;
}
void JfrEventSetting::unhide_internal_types() {
_internal_types = true;
}
bool JfrEventSetting::is_internal_types_visible() {
return _internal_types;
}
#ifdef ASSERT
bool JfrEventSetting::bounds_check_event(jlong id) {
if ((unsigned)id < FIRST_EVENT_ID) {
@ -69,3 +79,4 @@ bool JfrEventSetting::bounds_check_event(jlong id) {
return true;
}
#endif // ASSERT

View File

@ -36,6 +36,7 @@ class JfrEventSetting : AllStatic {
private:
static JfrNativeSettings _jvm_event_settings;
static jfrNativeEventSetting& setting(JfrEventId event_id);
static bool _internal_types;
public:
static void set_enabled(jlong event_id, bool enabled);
@ -48,6 +49,8 @@ class JfrEventSetting : AllStatic {
static jlong cutoff(JfrEventId event_id);
static bool is_large(JfrEventId event_id);
static void set_large(JfrEventId event_id);
static void unhide_internal_types();
static bool is_internal_types_visible();
DEBUG_ONLY(static bool bounds_check_event(jlong id);)
};

View File

@ -241,4 +241,9 @@ public final class EventType {
PlatformEventType getPlatformEventType() {
return platformEventType;
}
// package private
boolean isVisible() {
return platformEventType.isVisible();
}
}

View File

@ -203,6 +203,11 @@ public final class FlightRecorderPermission extends java.security.BasicPermissio
public EventSettings newEventSettings(EventSettingsModifier esm) {
return new EventSettings.DelegatedEventSettings(esm);
}
@Override
public boolean isVisible(EventType t) {
return t.isVisible();
}
}
/**

View File

@ -292,7 +292,7 @@ public final class EventControl {
}
ActiveSettingEvent event = ActiveSettingEvent.EVENT.get();
for (NamedControl nc : namedControls) {
if (Utils.isSettingVisible(nc.control, type.hasEventHook())) {
if (Utils.isSettingVisible(nc.control, type.hasEventHook()) && type.isVisible()) {
String value = nc.control.getLastValue();
if (value == null) {
value = nc.control.getDefaultValue();

View File

@ -125,14 +125,22 @@ final class JVMUpcalls {
}
}
/**
* Called by the JVM to ensure metadata for internal events/types become public.
*
* Must be called after metadata repository has been initialized (JFR created).
*
*/
static void unhideInternalTypes() {
MetadataRepository.unhideInternalTypes();
}
/**
* Called by the JVM to create the recorder thread.
*
* @param systemThreadGroup
* the system thread group
* @param systemThreadGroup the system thread group
*
* @param contextClassLoader
* the context class loader.
* @param contextClassLoader the context class loader.
*
* @return a new thread
*/

View File

@ -53,7 +53,8 @@ public final class MetadataLoader {
// Caching to reduce allocation pressure and heap usage
private final AnnotationElement RELATIONAL = new AnnotationElement(Relational.class);
private final AnnotationElement ENABLED = new AnnotationElement(Enabled.class, false);
private final AnnotationElement ENABLED = new AnnotationElement(Enabled.class, true);
private final AnnotationElement DISABLED = new AnnotationElement(Enabled.class, false);
private final AnnotationElement THRESHOLD = new AnnotationElement(Threshold.class, "0 ns");
private final AnnotationElement STACK_TRACE = new AnnotationElement(StackTrace.class, true);
private final AnnotationElement TRANSITION_TO = new AnnotationElement(TransitionTo.class);
@ -82,6 +83,7 @@ public final class MetadataLoader {
private final boolean isEvent;
private final boolean isRelation;
private final boolean experimental;
private final boolean internal;
private final long id;
public TypeElement(DataInputStream dis) throws IOException {
@ -101,6 +103,7 @@ public final class MetadataLoader {
cutoff = dis.readBoolean();
throttle = dis.readBoolean();
experimental = dis.readBoolean();
internal = dis.readBoolean();
id = dis.readLong();
isEvent = dis.readBoolean();
isRelation = dis.readBoolean();
@ -315,7 +318,11 @@ public final class MetadataLoader {
}
Type type;
if (t.isEvent) {
aes.add(ENABLED);
if (t.internal) {
aes.add(ENABLED);
} else {
aes.add(DISABLED);
}
type = new PlatformEventType(t.name, t.id, false, true);
} else {
type = knownTypeMap.get(t.name);
@ -328,6 +335,15 @@ public final class MetadataLoader {
}
}
}
if (t.internal) {
type.setInternal(true);
// Internal types are hidden by default
type.setVisible(false);
// Internal events are enabled by default
if (type instanceof PlatformEventType pe) {
pe.setEnabled(true);
}
}
type.setAnnotations(aes);
typeMap.put(t.name, type);
}

View File

@ -34,6 +34,7 @@ import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -71,7 +72,7 @@ public final class MetadataRepository {
private void initializeJVMEventTypes() {
List<RequestHook> requestHooks = new ArrayList<>();
for (Type type : typeLibrary.getTypes()) {
for (Type type : new ArrayList<>(typeLibrary.getTypes())) {
if (type instanceof PlatformEventType pEventType) {
EventType eventType = PrivateAccess.getInstance().newEventType(pEventType);
pEventType.setHasDuration(eventType.getAnnotation(Threshold.class) != null);
@ -106,7 +107,11 @@ public final class MetadataRepository {
eventTypes.add(h.getEventType());
}
}
eventTypes.addAll(nativeEventTypes);
for (EventType t : nativeEventTypes) {
if (PrivateAccess.getInstance().isVisible(t)) {
eventTypes.add(t);
}
}
return eventTypes;
}
@ -243,7 +248,13 @@ public final class MetadataRepository {
ByteArrayOutputStream baos = new ByteArrayOutputStream(40000);
DataOutputStream daos = new DataOutputStream(baos);
try {
List<Type> types = typeLibrary.getTypes();
List<Type> types = typeLibrary.getVisibleTypes();
if (Logger.shouldLog(LogTag.JFR_METADATA, LogLevel.DEBUG)) {
Collections.sort(types,Comparator.comparing(Type::getName));
for (Type t: types) {
Logger.log(LogTag.JFR_METADATA, LogLevel.INFO, "Serialized type: " + t.getName() + " id=" + t.getId());
}
}
Collections.sort(types);
MetadataDescriptor.write(types, daos);
daos.flush();
@ -349,4 +360,20 @@ public final class MetadataRepository {
jvm.flush();
}
static void unhideInternalTypes() {
for (Type t : TypeLibrary.getInstance().getTypes()) {
if (t.isInternal()) {
t.setVisible(true);
Logger.log(LogTag.JFR_METADATA, LogLevel.DEBUG, "Unhiding internal type " + t.getName());
}
}
// Singleton should have been initialized here.
// It's not possible to call MetadataRepository().getInstance(),
// because it will deadlock with Java thread calling flush() or setOutput();
instance.storeDescriptorInJVM();
}
public synchronized List<Type> getVisibleTypes() {
return typeLibrary.getVisibleTypes();
}
}

View File

@ -103,4 +103,6 @@ public abstract class PrivateAccess {
public abstract AccessControlContext getContext(SettingControl sc);
public abstract EventSettings newEventSettings(EventSettingsModifier esm);
public abstract boolean isVisible(EventType t);
}

View File

@ -89,6 +89,8 @@ public class Type implements Comparable<Type> {
private Boolean simpleType; // calculated lazy
private boolean remove = true;
private long id;
private boolean visible = true;
private boolean internal;
/**
* Creates a type
@ -337,4 +339,20 @@ public class Type implements Comparable<Type> {
public void setId(long id) {
this.id = id;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public boolean isVisible() {
return visible;
}
public void setInternal(boolean internal) {
this.internal = internal;
}
public boolean isInternal() {
return internal;
}
}

View File

@ -119,8 +119,19 @@ public final class TypeLibrary {
}
}
public List<Type> getTypes() {
return new ArrayList<>(types.values());
public Collection<Type> getTypes() {
return types.values();
}
// Returned list should be mutable (for in-place sorting)
public List<Type> getVisibleTypes() {
List<Type> visible = new ArrayList<>(types.size());
types.values().forEach(t -> {
if (t.isVisible()) {
visible.add(t);
}
});
return visible;
}
public static Type createAnnotationType(Class<? extends Annotation> a) {

View File

@ -42,7 +42,7 @@ import jdk.jfr.consumer.RecordingFile;
import jdk.jfr.internal.PlatformEventType;
import jdk.jfr.internal.PrivateAccess;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.TypeLibrary;
import jdk.jfr.internal.MetadataRepository;
import jdk.jfr.internal.consumer.JdkJfrConsumer;
import static java.nio.charset.StandardCharsets.UTF_8;
@ -230,7 +230,7 @@ final class Metadata extends Command {
if (file == null) {
// Force initialization
FlightRecorder.getFlightRecorder().getEventTypes();
return TypeLibrary.getInstance().getTypes();
return MetadataRepository.getInstance().getVisibleTypes();
}
try (RecordingFile rf = new RecordingFile(file)) {
return PRIVATE_ACCESS.readTypes(rf);

View File

@ -775,11 +775,6 @@
<setting name="threshold">0 ms</setting>
</event>
<event name="jdk.ZThreadDebug">
<setting name="enabled">true</setting>
<setting name="threshold">0 ms</setting>
</event>
<event name="jdk.ZUncommit">
<setting name="enabled">true</setting>
<setting name="threshold">0 ms</setting>

View File

@ -775,11 +775,6 @@
<setting name="threshold">0 ms</setting>
</event>
<event name="jdk.ZThreadDebug">
<setting name="enabled">true</setting>
<setting name="threshold">0 ms</setting>
</event>
<event name="jdk.ZUncommit">
<setting name="enabled">true</setting>
<setting name="threshold">0 ms</setting>