Skip to content
Permalink
Browse files
8211230: JFR: internal events
Reviewed-by: mgronlun
  • Loading branch information
egahlin committed Dec 9, 2021
1 parent 965ea8d commit 08aad8506e60157fc5ee1cc0e3e90cf1c35b3df5
Showing 20 changed files with 219 additions and 32 deletions.
@@ -174,6 +174,7 @@ static class TypeElement {
boolean cutoff;
boolean throttle;
boolean experimental;
boolean internal;
long id;
boolean isEvent;
boolean isRelation;
@@ -197,6 +198,7 @@ public void persist(DataOutputStream pos) throws IOException {
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 void startElement(String uri, String localName, String qName, Attributes
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 @@ private static void printEvent(Printer out, TypeElement event, boolean empty) {
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;");
@@ -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;
}
@@ -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
@@ -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>
@@ -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>
@@ -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;
}
@@ -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

@@ -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);)
};
@@ -241,4 +241,9 @@ Type getType() {
PlatformEventType getPlatformEventType() {
return platformEventType;
}

// package private
boolean isVisible() {
return platformEventType.isVisible();
}
}
@@ -203,6 +203,11 @@ public AccessControlContext getContext(SettingControl settingControl) {
public EventSettings newEventSettings(EventSettingsModifier esm) {
return new EventSettings.DelegatedEventSettings(esm);
}

@Override
public boolean isVisible(EventType t) {
return t.isVisible();
}
}

/**
@@ -292,7 +292,7 @@ void writeActiveSettingEvent() {
}
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();
@@ -125,14 +125,22 @@ static byte[] bytesForEagerInstrumentation(long traceId, boolean forceInstrument
}
}

/**
* 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
*/
@@ -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 @@ private static final class TypeElement {
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 TypeElement(DataInputStream dis) throws IOException {
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 @@ private Map<String, Type> buildTypeMap() {
}
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 @@ private Map<String, Type> buildTypeMap() {
}
}
}
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);
}

1 comment on commit 08aad85

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 08aad85 Dec 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.