8343026: JFR: Index into fields in the topFrame
Reviewed-by: mgronlun
This commit is contained in:
parent
d8b3685d36
commit
7c800e6bae
@ -38,6 +38,7 @@ import jdk.jfr.AnnotationElement;
|
||||
import jdk.jfr.Event;
|
||||
import jdk.jfr.SettingControl;
|
||||
import jdk.jfr.ValueDescriptor;
|
||||
import jdk.jfr.internal.util.Utils;
|
||||
|
||||
/**
|
||||
* Internal data structure that describes a type,
|
||||
@ -185,15 +186,10 @@ public class Type implements Comparable<Type> {
|
||||
Type type = PrivateAccess.getInstance().getType(subField);
|
||||
return type.getField(post);
|
||||
}
|
||||
} else {
|
||||
for (ValueDescriptor v : getFields()) {
|
||||
if (name.equals(v.getName())) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return Utils.findField(getFields(), name);
|
||||
}
|
||||
|
||||
public List<ValueDescriptor> getFields() {
|
||||
if (fields instanceof ArrayList<?> list) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 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
|
||||
@ -49,6 +49,9 @@ import jdk.jfr.consumer.RecordedClassLoader;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.jfr.consumer.RecordedFrame;
|
||||
import jdk.jfr.consumer.RecordedStackTrace;
|
||||
import jdk.jfr.internal.PrivateAccess;
|
||||
import jdk.jfr.internal.Type;
|
||||
import jdk.jfr.internal.util.Utils;
|
||||
|
||||
/**
|
||||
* This is a helper class to QueryResolver. It handles the creation of fields
|
||||
@ -60,9 +63,9 @@ import jdk.jfr.consumer.RecordedStackTrace;
|
||||
final class FieldBuilder {
|
||||
private static final Set<String> KNOWN_TYPES = createKnownTypes();
|
||||
private final List<EventType> eventTypes;
|
||||
private final ValueDescriptor descriptor;
|
||||
private final Field field;
|
||||
private final String fieldName;
|
||||
private ValueDescriptor descriptor;
|
||||
|
||||
public FieldBuilder(List<EventType> eventTypes, FilteredType type, String fieldName) {
|
||||
this.eventTypes = eventTypes;
|
||||
@ -77,12 +80,15 @@ final class FieldBuilder {
|
||||
return List.of(field);
|
||||
}
|
||||
|
||||
configureAliases();
|
||||
if (descriptor != null) {
|
||||
field.fixedWidth = !descriptor.getTypeName().equals("java.lang.String");
|
||||
field.dataType = descriptor.getTypeName();
|
||||
field.label = makeLabel(descriptor, hasDuration());
|
||||
field.alignLeft = true;
|
||||
if (field.valueGetter == null) {
|
||||
field.valueGetter = valueGetter(field.name);
|
||||
}
|
||||
|
||||
configureNumericTypes();
|
||||
configureTime();
|
||||
@ -113,22 +119,6 @@ final class FieldBuilder {
|
||||
}
|
||||
|
||||
private boolean configureSyntheticFields() {
|
||||
if (fieldName.equals("stackTrace.topApplicationFrame")) {
|
||||
configureTopApplicationFrameField();
|
||||
return true;
|
||||
}
|
||||
if (fieldName.equals("stackTrace.notInit")) {
|
||||
configureNotInitFrameField();
|
||||
return true;
|
||||
}
|
||||
if (fieldName.equals("stackTrace.topFrame.class")) {
|
||||
configureTopFrameClassField();
|
||||
return true;
|
||||
}
|
||||
if (fieldName.equals("stackTrace.topFrame")) {
|
||||
configureTopFrameField();
|
||||
return true;
|
||||
}
|
||||
if (fieldName.equals("id") && field.type.getName().equals("jdk.ActiveSetting")) {
|
||||
configureEventTypeIdField();
|
||||
return true;
|
||||
@ -144,6 +134,73 @@ final class FieldBuilder {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void configureAliases() {
|
||||
configureFrame("topFrame", FieldBuilder::topFrame);
|
||||
configureFrame("topApplicationFrame", FieldBuilder::topApplicationFrame);
|
||||
configureFrame("topNotInitFrame", FieldBuilder::topNotInitFrame);
|
||||
}
|
||||
|
||||
private void configureFrame(String frameName, Function<RecordedEvent, Object> getter) {
|
||||
String name = "stackTrace." + frameName;
|
||||
if (!fieldName.startsWith(name)) {
|
||||
return;
|
||||
}
|
||||
ValueDescriptor stackTrace = Utils.findField(field.type.getFields(), "stackTrace");
|
||||
if (stackTrace == null) {
|
||||
return;
|
||||
}
|
||||
ValueDescriptor frames = Utils.findField(stackTrace.getFields(), "frames");
|
||||
if (frames == null) {
|
||||
return;
|
||||
}
|
||||
int length = name.length();
|
||||
if (fieldName.length() == length) {
|
||||
descriptor = frames; // Use array descriptor for now
|
||||
field.valueGetter = getter;
|
||||
return;
|
||||
}
|
||||
String subName = fieldName.substring(length + 1);
|
||||
Type type = PrivateAccess.getInstance().getType(frames);
|
||||
ValueDescriptor subField = type.getField(subName);
|
||||
if (subField != null) {
|
||||
descriptor = subField;
|
||||
field.valueGetter = e -> {
|
||||
if (getter.apply(e) instanceof RecordedFrame frame) {
|
||||
return frame.getValue(subName);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static RecordedFrame topFrame(RecordedEvent event) {
|
||||
return findJavaFrame(event, x -> true);
|
||||
}
|
||||
|
||||
private static RecordedFrame topApplicationFrame(RecordedEvent event) {
|
||||
return findJavaFrame(event, frame -> {
|
||||
RecordedClass cl = frame.getMethod().getType();
|
||||
RecordedClassLoader classLoader = cl.getClassLoader();
|
||||
return classLoader != null && !"bootstrap".equals(classLoader.getName());
|
||||
});
|
||||
}
|
||||
|
||||
private static Object topNotInitFrame(RecordedEvent event) {
|
||||
return findJavaFrame(event, frame -> !frame.getMethod().getName().equals("<init>"));
|
||||
}
|
||||
|
||||
private static RecordedFrame findJavaFrame(RecordedEvent event, Predicate<RecordedFrame> condition) {
|
||||
RecordedStackTrace st = event.getStackTrace();
|
||||
if (st != null) {
|
||||
for (RecordedFrame frame : st.getFrames()) {
|
||||
if (frame.isJavaFrame() && condition.test(frame)) {
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void configureEventTypeIdField() {
|
||||
Map<Long, String> eventTypes = createEventTypeLookup();
|
||||
field.alignLeft = true;
|
||||
@ -166,65 +223,6 @@ final class FieldBuilder {
|
||||
return map;
|
||||
}
|
||||
|
||||
private void configureTopFrameField() {
|
||||
field.alignLeft = true;
|
||||
field.label = "Method";
|
||||
field.dataType = "jdk.types.Method";
|
||||
field.valueGetter = e -> {
|
||||
RecordedStackTrace t = e.getStackTrace();
|
||||
return t != null ? t.getFrames().getFirst() : null;
|
||||
};
|
||||
field.lexicalSort = true;
|
||||
}
|
||||
|
||||
private void configureTopFrameClassField() {
|
||||
field.alignLeft = true;
|
||||
field.label = "Class";
|
||||
field.dataType = "java.lang.Class";
|
||||
field.valueGetter = e -> {
|
||||
RecordedStackTrace t = e.getStackTrace();
|
||||
if (t == null) {
|
||||
return null;
|
||||
}
|
||||
return t.getFrames().getFirst().getMethod().getType();
|
||||
};
|
||||
field.lexicalSort = true;
|
||||
}
|
||||
|
||||
private void configureCustomFrame(Predicate<RecordedFrame> condition) {
|
||||
field.alignLeft = true;
|
||||
field.dataType = "jdk.types.Frame";
|
||||
field.label = "Method";
|
||||
field.lexicalSort = true;
|
||||
field.valueGetter = e -> {
|
||||
RecordedStackTrace t = e.getStackTrace();
|
||||
if (t != null) {
|
||||
for (RecordedFrame f : t.getFrames()) {
|
||||
if (f.isJavaFrame()) {
|
||||
if (condition.test(f)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
private void configureNotInitFrameField() {
|
||||
configureCustomFrame(frame -> {
|
||||
return !frame.getMethod().getName().equals("<init>");
|
||||
});
|
||||
}
|
||||
|
||||
private void configureTopApplicationFrameField() {
|
||||
configureCustomFrame(frame -> {
|
||||
RecordedClass cl = frame.getMethod().getType();
|
||||
RecordedClassLoader classLoader = cl.getClassLoader();
|
||||
return classLoader != null && !"bootstrap".equals(classLoader.getName());
|
||||
});
|
||||
}
|
||||
|
||||
private void configureEventType(Function<RecordedEvent, Object> retriever) {
|
||||
field.alignLeft = true;
|
||||
field.dataType = String.class.getName();
|
||||
@ -234,6 +232,9 @@ final class FieldBuilder {
|
||||
}
|
||||
|
||||
private static String makeLabel(ValueDescriptor v, boolean hasDuration) {
|
||||
if (v.getTypeName().equals("jdk.types.StackFrame")) {
|
||||
return "Method";
|
||||
}
|
||||
String label = v.getLabel();
|
||||
if (label == null) {
|
||||
return v.getName();
|
||||
|
@ -186,7 +186,7 @@ table = "COLUMN 'Monitor Address', 'Class', 'Threads', 'Max Duration'
|
||||
label = "Deprecated Methods for Removal"
|
||||
table = "COLUMN 'Deprecated Method', 'Called from Class'
|
||||
FORMAT truncate-beginning, cell-height:10000;truncate-beginning
|
||||
SELECT method AS m, SET(stackTrace.topFrame.class)
|
||||
SELECT method AS m, SET(stackTrace.topFrame.method.type)
|
||||
FROM DeprecatedInvocation
|
||||
WHERE forRemoval = 'true'
|
||||
GROUP BY m
|
||||
@ -266,7 +266,7 @@ table = "COLUMN 'Message', 'Count'
|
||||
[application.exception-by-site]
|
||||
label ="Exceptions by Site"
|
||||
table = "COLUMN 'Method', 'Count'
|
||||
SELECT stackTrace.notInit AS S, COUNT(startTime) AS C
|
||||
SELECT stackTrace.topNotInitFrame AS S, COUNT(startTime) AS C
|
||||
FROM JavaErrorThrow, JavaExceptionThrow GROUP BY S ORDER BY C DESC"
|
||||
|
||||
[application.file-reads-by-path]
|
||||
|
@ -48,6 +48,7 @@ import jdk.internal.module.Checks;
|
||||
import jdk.jfr.Event;
|
||||
import jdk.jfr.EventType;
|
||||
import jdk.jfr.RecordingState;
|
||||
import jdk.jfr.ValueDescriptor;
|
||||
import jdk.jfr.internal.LogLevel;
|
||||
import jdk.jfr.internal.LogTag;
|
||||
import jdk.jfr.internal.Logger;
|
||||
@ -438,4 +439,13 @@ public final class Utils {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static ValueDescriptor findField(List<ValueDescriptor> fields, String name) {
|
||||
for (ValueDescriptor v : fields) {
|
||||
if (v.getName().equals(name)) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user