1
1
/*
2
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
49
49
import jdk .jfr .consumer .RecordedEvent ;
50
50
import jdk .jfr .consumer .RecordedFrame ;
51
51
import jdk .jfr .consumer .RecordedStackTrace ;
52
+ import jdk .jfr .internal .PrivateAccess ;
53
+ import jdk .jfr .internal .Type ;
54
+ import jdk .jfr .internal .util .Utils ;
52
55
53
56
/**
54
57
* This is a helper class to QueryResolver. It handles the creation of fields
60
63
final class FieldBuilder {
61
64
private static final Set <String > KNOWN_TYPES = createKnownTypes ();
62
65
private final List <EventType > eventTypes ;
63
- private final ValueDescriptor descriptor ;
64
66
private final Field field ;
65
67
private final String fieldName ;
68
+ private ValueDescriptor descriptor ;
66
69
67
70
public FieldBuilder (List <EventType > eventTypes , FilteredType type , String fieldName ) {
68
71
this .eventTypes = eventTypes ;
@@ -77,12 +80,15 @@ public List<Field> build() {
77
80
return List .of (field );
78
81
}
79
82
83
+ configureAliases ();
80
84
if (descriptor != null ) {
81
85
field .fixedWidth = !descriptor .getTypeName ().equals ("java.lang.String" );
82
86
field .dataType = descriptor .getTypeName ();
83
87
field .label = makeLabel (descriptor , hasDuration ());
84
88
field .alignLeft = true ;
85
- field .valueGetter = valueGetter (field .name );
89
+ if (field .valueGetter == null ) {
90
+ field .valueGetter = valueGetter (field .name );
91
+ }
86
92
87
93
configureNumericTypes ();
88
94
configureTime ();
@@ -113,22 +119,6 @@ private boolean hasDuration() {
113
119
}
114
120
115
121
private boolean configureSyntheticFields () {
116
- if (fieldName .equals ("stackTrace.topApplicationFrame" )) {
117
- configureTopApplicationFrameField ();
118
- return true ;
119
- }
120
- if (fieldName .equals ("stackTrace.notInit" )) {
121
- configureNotInitFrameField ();
122
- return true ;
123
- }
124
- if (fieldName .equals ("stackTrace.topFrame.class" )) {
125
- configureTopFrameClassField ();
126
- return true ;
127
- }
128
- if (fieldName .equals ("stackTrace.topFrame" )) {
129
- configureTopFrameField ();
130
- return true ;
131
- }
132
122
if (fieldName .equals ("id" ) && field .type .getName ().equals ("jdk.ActiveSetting" )) {
133
123
configureEventTypeIdField ();
134
124
return true ;
@@ -144,6 +134,73 @@ private boolean configureSyntheticFields() {
144
134
return false ;
145
135
}
146
136
137
+ private void configureAliases () {
138
+ configureFrame ("topFrame" , FieldBuilder ::topFrame );
139
+ configureFrame ("topApplicationFrame" , FieldBuilder ::topApplicationFrame );
140
+ configureFrame ("topNotInitFrame" , FieldBuilder ::topNotInitFrame );
141
+ }
142
+
143
+ private void configureFrame (String frameName , Function <RecordedEvent , Object > getter ) {
144
+ String name = "stackTrace." + frameName ;
145
+ if (!fieldName .startsWith (name )) {
146
+ return ;
147
+ }
148
+ ValueDescriptor stackTrace = Utils .findField (field .type .getFields (), "stackTrace" );
149
+ if (stackTrace == null ) {
150
+ return ;
151
+ }
152
+ ValueDescriptor frames = Utils .findField (stackTrace .getFields (), "frames" );
153
+ if (frames == null ) {
154
+ return ;
155
+ }
156
+ int length = name .length ();
157
+ if (fieldName .length () == length ) {
158
+ descriptor = frames ; // Use array descriptor for now
159
+ field .valueGetter = getter ;
160
+ return ;
161
+ }
162
+ String subName = fieldName .substring (length + 1 );
163
+ Type type = PrivateAccess .getInstance ().getType (frames );
164
+ ValueDescriptor subField = type .getField (subName );
165
+ if (subField != null ) {
166
+ descriptor = subField ;
167
+ field .valueGetter = e -> {
168
+ if (getter .apply (e ) instanceof RecordedFrame frame ) {
169
+ return frame .getValue (subName );
170
+ }
171
+ return null ;
172
+ };
173
+ }
174
+ }
175
+
176
+ private static RecordedFrame topFrame (RecordedEvent event ) {
177
+ return findJavaFrame (event , x -> true );
178
+ }
179
+
180
+ private static RecordedFrame topApplicationFrame (RecordedEvent event ) {
181
+ return findJavaFrame (event , frame -> {
182
+ RecordedClass cl = frame .getMethod ().getType ();
183
+ RecordedClassLoader classLoader = cl .getClassLoader ();
184
+ return classLoader != null && !"bootstrap" .equals (classLoader .getName ());
185
+ });
186
+ }
187
+
188
+ private static Object topNotInitFrame (RecordedEvent event ) {
189
+ return findJavaFrame (event , frame -> !frame .getMethod ().getName ().equals ("<init>" ));
190
+ }
191
+
192
+ private static RecordedFrame findJavaFrame (RecordedEvent event , Predicate <RecordedFrame > condition ) {
193
+ RecordedStackTrace st = event .getStackTrace ();
194
+ if (st != null ) {
195
+ for (RecordedFrame frame : st .getFrames ()) {
196
+ if (frame .isJavaFrame () && condition .test (frame )) {
197
+ return frame ;
198
+ }
199
+ }
200
+ }
201
+ return null ;
202
+ }
203
+
147
204
private void configureEventTypeIdField () {
148
205
Map <Long , String > eventTypes = createEventTypeLookup ();
149
206
field .alignLeft = true ;
@@ -166,65 +223,6 @@ private Map<Long, String> createEventTypeLookup() {
166
223
return map ;
167
224
}
168
225
169
- private void configureTopFrameField () {
170
- field .alignLeft = true ;
171
- field .label = "Method" ;
172
- field .dataType = "jdk.types.Method" ;
173
- field .valueGetter = e -> {
174
- RecordedStackTrace t = e .getStackTrace ();
175
- return t != null ? t .getFrames ().getFirst () : null ;
176
- };
177
- field .lexicalSort = true ;
178
- }
179
-
180
- private void configureTopFrameClassField () {
181
- field .alignLeft = true ;
182
- field .label = "Class" ;
183
- field .dataType = "java.lang.Class" ;
184
- field .valueGetter = e -> {
185
- RecordedStackTrace t = e .getStackTrace ();
186
- if (t == null ) {
187
- return null ;
188
- }
189
- return t .getFrames ().getFirst ().getMethod ().getType ();
190
- };
191
- field .lexicalSort = true ;
192
- }
193
-
194
- private void configureCustomFrame (Predicate <RecordedFrame > condition ) {
195
- field .alignLeft = true ;
196
- field .dataType = "jdk.types.Frame" ;
197
- field .label = "Method" ;
198
- field .lexicalSort = true ;
199
- field .valueGetter = e -> {
200
- RecordedStackTrace t = e .getStackTrace ();
201
- if (t != null ) {
202
- for (RecordedFrame f : t .getFrames ()) {
203
- if (f .isJavaFrame ()) {
204
- if (condition .test (f )) {
205
- return f ;
206
- }
207
- }
208
- }
209
- }
210
- return null ;
211
- };
212
- }
213
-
214
- private void configureNotInitFrameField () {
215
- configureCustomFrame (frame -> {
216
- return !frame .getMethod ().getName ().equals ("<init>" );
217
- });
218
- }
219
-
220
- private void configureTopApplicationFrameField () {
221
- configureCustomFrame (frame -> {
222
- RecordedClass cl = frame .getMethod ().getType ();
223
- RecordedClassLoader classLoader = cl .getClassLoader ();
224
- return classLoader != null && !"bootstrap" .equals (classLoader .getName ());
225
- });
226
- }
227
-
228
226
private void configureEventType (Function <RecordedEvent , Object > retriever ) {
229
227
field .alignLeft = true ;
230
228
field .dataType = String .class .getName ();
@@ -234,6 +232,9 @@ private void configureEventType(Function<RecordedEvent, Object> retriever) {
234
232
}
235
233
236
234
private static String makeLabel (ValueDescriptor v , boolean hasDuration ) {
235
+ if (v .getTypeName ().equals ("jdk.types.StackFrame" )) {
236
+ return "Method" ;
237
+ }
237
238
String label = v .getLabel ();
238
239
if (label == null ) {
239
240
return v .getName ();
0 commit comments