109 // JDK-8157024 constant for the field id 110 private static final String UNALLOCATED_CAPACITY_FIELD_ID = "unallocatedCapacity"; //$NON-NLS-1$ 111 112 private final IEventSink sink; 113 private final Object[] reusableArray = new Object[FIELDS.size()]; 114 private int endTimeIndex = -1; 115 private int typeIndex = -1; 116 private int enabledIndex = -1; 117 private int stacktraceIndex = -1; 118 private int thresholdIndex = -1; 119 private int periodIndex = -1; 120 121 static { 122 attributeRenameMap = buildRenameMap(); 123 } 124 125 @SuppressWarnings("nls") 126 private static HashMap<String, Map<String, String>> buildRenameMap() { 127 // NOTE: Replace the last string argument with an identifier reference if a matching one is added to JfrAttributes. 128 HashMap<String, Map<String, String>> map = new HashMap<>(); 129 addRenameEntry(map, JdkTypeIDsPreJdk9.THREAD_PARK, "klass", "parkedClass"); 130 addRenameEntry(map, JdkTypeIDsPreJdk9.MONITOR_ENTER, "klass", JdkAttributes.MONITOR_CLASS.getIdentifier()); 131 addRenameEntry(map, JdkTypeIDsPreJdk9.MONITOR_WAIT, "klass", JdkAttributes.MONITOR_CLASS.getIdentifier()); 132 addRenameEntry(map, JdkTypeIDsPreJdk9.INT_FLAG_CHANGED, "old_value", "oldValue"); 133 addRenameEntry(map, JdkTypeIDsPreJdk9.INT_FLAG_CHANGED, "new_value", "newValue"); 134 addRenameEntry(map, JdkTypeIDsPreJdk9.UINT_FLAG_CHANGED, "old_value", "oldValue"); 135 addRenameEntry(map, JdkTypeIDsPreJdk9.UINT_FLAG_CHANGED, "new_value", "newValue"); 136 addRenameEntry(map, JdkTypeIDsPreJdk9.LONG_FLAG_CHANGED, "old_value", "oldValue"); 137 addRenameEntry(map, JdkTypeIDsPreJdk9.LONG_FLAG_CHANGED, "new_value", "newValue"); 138 addRenameEntry(map, JdkTypeIDsPreJdk9.ULONG_FLAG_CHANGED, "old_value", "oldValue"); 139 addRenameEntry(map, JdkTypeIDsPreJdk9.ULONG_FLAG_CHANGED, "new_value", "newValue"); 140 addRenameEntry(map, JdkTypeIDsPreJdk9.DOUBLE_FLAG_CHANGED, "old_value", "oldValue"); 141 addRenameEntry(map, JdkTypeIDsPreJdk9.DOUBLE_FLAG_CHANGED, "new_value", "newValue"); 142 addRenameEntry(map, JdkTypeIDsPreJdk9.BOOLEAN_FLAG_CHANGED, "old_value", "oldValue"); 143 addRenameEntry(map, JdkTypeIDsPreJdk9.BOOLEAN_FLAG_CHANGED, "new_value", "newValue"); 144 addRenameEntry(map, JdkTypeIDsPreJdk9.STRING_FLAG_CHANGED, "old_value", "oldValue"); 145 addRenameEntry(map, JdkTypeIDsPreJdk9.STRING_FLAG_CHANGED, "new_value", "newValue"); 146 addRenameEntry(map, JdkTypeIDsPreJdk9.GC_DETAILED_EVACUATION_INFO, "allocRegionsUsedBefore", 147 "allocationRegionsUsedBefore"); 148 addRenameEntry(map, JdkTypeIDsPreJdk9.GC_DETAILED_EVACUATION_INFO, "allocRegionsUsedAfter", 149 "allocationRegionsUsedAfter"); 150 addRenameEntry(map, JdkTypeIDsPreJdk9.SWEEP_CODE_CACHE, "sweepIndex", "sweepId"); 151 addRenameEntry(map, JdkTypeIDsPreJdk9.ALLOC_INSIDE_TLAB, "class", 152 JdkAttributes.ALLOCATION_CLASS.getIdentifier()); 153 addRenameEntry(map, JdkTypeIDsPreJdk9.ALLOC_OUTSIDE_TLAB, "class", 154 JdkAttributes.ALLOCATION_CLASS.getIdentifier()); 155 addRenameEntry(map, JdkTypeIDsPreJdk9.OBJECT_COUNT, "class", JdkAttributes.OBJECT_CLASS.getIdentifier()); 156 addRenameEntry(map, JdkTypeIDsPreJdk9.COMPILER_PHASE, "compileID", 157 JdkAttributes.COMPILER_COMPILATION_ID.getIdentifier()); 158 addRenameEntry(map, JdkTypeIDsPreJdk9.COMPILATION, "compileID", 159 JdkAttributes.COMPILER_COMPILATION_ID.getIdentifier()); 160 addRenameEntry(map, JdkTypeIDsPreJdk9.COMPILER_FAILURE, "compileID", 161 JdkAttributes.COMPILER_COMPILATION_ID.getIdentifier()); 162 addRenameEntry(map, JdkTypeIDsPreJdk9.COMPILER_FAILURE, "failure", 163 JdkAttributes.COMPILER_FAILED_MESSAGE.getIdentifier()); 164 addRenameEntry(map, JdkTypeIDsPreJdk9.GC_DETAILED_OBJECT_COUNT_AFTER_GC, "class", 165 JdkAttributes.OBJECT_CLASS.getIdentifier()); 166 return map; 167 } 168 169 private static void addRenameEntry( 170 Map<String, Map<String, String>> renameMap, String eventId, String pre9AttrId, String attrId) { 171 Map<String, String> attrMap = renameMap.get(eventId); 172 if (attrMap == null) { 173 attrMap = new HashMap<>(); 174 renameMap.put(eventId, attrMap); 175 } 176 attrMap.put(pre9AttrId, attrId); 177 } 178 179 SettingsTransformer(IEventSinkFactory sinkFactory, String label, String[] category, String description, 180 List<ValueField> dataStructure) { 181 sink = sinkFactory.create(JdkTypeIDs.RECORDING_SETTING, label, category, description, FIELDS); 182 for (int i = 0; i < dataStructure.size(); i++) { 183 ValueField vf = dataStructure.get(i); 184 if (vf.matches(JfrAttributes.END_TIME)) { 185 endTimeIndex = i; 186 } else if (vf.matches(SyntheticAttributeExtension.REC_SETTING_EVENT_ID_ATTRIBUTE)) { 187 typeIndex = i; 188 } else if (vf.matches(REC_SETTINGS_ATTR_ENABLED)) { 189 enabledIndex = i; 190 } else if (vf.matches(REC_SETTINGS_ATTR_STACKTRACE)) { 191 stacktraceIndex = i; 192 } else if (vf.matches(REC_SETTINGS_ATTR_THRESHOLD)) { 193 thresholdIndex = i; 194 } else if (vf.matches(REC_SETTINGS_ATTR_PERIOD)) { 195 periodIndex = i; 196 } 197 } 198 } 199 200 boolean isValid() { 201 return endTimeIndex >= 0 && typeIndex >= 0 && enabledIndex >= 0 && stacktraceIndex >= 0 && thresholdIndex >= 0 202 && periodIndex >= 0; 203 } 204 205 @Override 206 public void addEvent(Object[] values) { 207 LabeledIdentifier type = (LabeledIdentifier) values[typeIndex]; 208 if (type != null) { 209 type = new LabeledIdentifier(JdkTypeIDsPreJdk9.translate(type.getInterfaceId()), type.getImplementationId(), 210 type.getName(), type.getDeclaredDescription()); 211 } 212 Object startTime = values[endTimeIndex]; 213 214 addSettingEvent(startTime, type, REC_SETTING_NAME_ENABLED, values[enabledIndex]); 215 addSettingEvent(startTime, type, REC_SETTING_NAME_STACKTRACE, values[stacktraceIndex]); 216 addThresholdSettingEvent(startTime, type, (IQuantity) values[thresholdIndex]); 217 addPeriodSettingEvent(startTime, type, (IQuantity) values[periodIndex]); 218 } 219 220 private boolean addThresholdSettingEvent(Object startTime, LabeledIdentifier type, IQuantity quantity) { 221 // Remove thresholds with Long.MIN_VALUE ns duration as these are just padding for 222 // event types that cannot have thresholds. (At least JDK 7u75 used Long.MAX_VALUE.) 223 if (quantity != null) { 224 long numQuantity = quantity.longValue(); 225 if ((numQuantity != Long.MIN_VALUE) && (numQuantity != Long.MAX_VALUE)) { 226 addSettingEvent(startTime, type, REC_SETTING_NAME_THRESHOLD, quantity.persistableString()); 227 } 228 } 229 return false; 230 } 248 reusableArray[1] = type; 249 reusableArray[2] = settingName; 250 reusableArray[3] = settingValue == null ? null : settingValue.toString(); 251 sink.addEvent(reusableArray); 252 } 253 254 /* 255 * FIXME: Weird to explicitly wrap when the parser does exactly that. 256 * 257 * This class should be refactored into a parser extension although this may require a change to 258 * the API by adding priorities so that type transformation occurs before synthetic attributes 259 * are added. 260 */ 261 static IEventSinkFactory wrapSinkFactory(final IEventSinkFactory subFactory) { 262 return new IEventSinkFactory() { 263 264 @Override 265 public IEventSink create( 266 String identifier, String label, String[] category, String description, 267 List<ValueField> dataStructure) { 268 if (JdkTypeIDsPreJdk9.RECORDING_SETTING.equals(identifier)) { 269 SettingsTransformer st = new SettingsTransformer(subFactory, label, category, description, 270 dataStructure); 271 if (st.isValid()) { 272 return st; 273 } else { 274 // FIXME: Avoid System.err.println 275 System.err 276 .println("Cannot create SettingsTransformer from fields: " + dataStructure.toString()); //$NON-NLS-1$ 277 } 278 } else if (JdkTypeIDsPreJdk9.RECORDINGS.equals(identifier)) { 279 /* 280 * NOTE: Renaming 'duration' and 'startTime' attributes for JDK 8 'Recording' 281 * events so that they won't conflict with general attributes with the same 282 * names in JDK 9+ recordings. 283 */ 284 ValueField[] struct = new ValueField[dataStructure.size()]; 285 for (int i = 0; i < struct.length; i++) { 286 ValueField vf = dataStructure.get(i); 287 if (vf.matches(JfrAttributes.START_TIME)) { 288 vf = new ValueField(JdkAttributes.RECORDING_START); 289 } else if (vf.matches(JfrAttributes.DURATION)) { 290 vf = new ValueField(JdkAttributes.RECORDING_DURATION); 291 } 292 struct[i] = vf; 293 } 294 return subFactory.create(JdkTypeIDs.RECORDINGS, label, category, description, 295 Arrays.asList(struct)); 296 } else if (JdkTypeIDsPreJdk9.CODE_CACHE_STATISTICS.equals(identifier)) { 297 for (int i = 0; i < dataStructure.size(); i++) { 298 if (UNALLOCATED_CAPACITY_FIELD_ID.equals(dataStructure.get(i).getIdentifier())) { 299 return new FixCodeCacheSink(i, subFactory.create(JdkTypeIDsPreJdk9.translate(identifier), 300 label, category, description, dataStructure)); 301 } 302 } 303 } 304 return subFactory.create(JdkTypeIDsPreJdk9.translate(identifier), label, category, description, 305 translate(identifier, dataStructure)); 306 } 307 308 private List<ValueField> translate(String identifier, List<ValueField> dataStructure) { 309 Map<String, String> attrMap = attributeRenameMap.get(identifier); 310 if (attrMap == null) { 311 return dataStructure; 312 } 313 List<ValueField> renamedDataStructure = new ArrayList<>(); 314 for (ValueField vf : dataStructure) { 315 String renamedId = attrMap.get(vf.getIdentifier()); 316 if (renamedId == null) { 317 renamedDataStructure.add(vf); 318 } else { 319 renamedDataStructure 320 .add(new ValueField(renamedId, vf.getName(), vf.getDescription(), vf.getContentType())); 321 } 322 } 323 return renamedDataStructure; 324 } | 109 // JDK-8157024 constant for the field id 110 private static final String UNALLOCATED_CAPACITY_FIELD_ID = "unallocatedCapacity"; //$NON-NLS-1$ 111 112 private final IEventSink sink; 113 private final Object[] reusableArray = new Object[FIELDS.size()]; 114 private int endTimeIndex = -1; 115 private int typeIndex = -1; 116 private int enabledIndex = -1; 117 private int stacktraceIndex = -1; 118 private int thresholdIndex = -1; 119 private int periodIndex = -1; 120 121 static { 122 attributeRenameMap = buildRenameMap(); 123 } 124 125 @SuppressWarnings("nls") 126 private static HashMap<String, Map<String, String>> buildRenameMap() { 127 // NOTE: Replace the last string argument with an identifier reference if a matching one is added to JfrAttributes. 128 HashMap<String, Map<String, String>> map = new HashMap<>(); 129 addRenameEntry(map, JdkTypeIDsPreJdk11.THREAD_PARK, "klass", "parkedClass"); 130 addRenameEntry(map, JdkTypeIDsPreJdk11.MONITOR_ENTER, "klass", JdkAttributes.MONITOR_CLASS.getIdentifier()); 131 addRenameEntry(map, JdkTypeIDsPreJdk11.MONITOR_WAIT, "klass", JdkAttributes.MONITOR_CLASS.getIdentifier()); 132 addRenameEntry(map, JdkTypeIDsPreJdk11.INT_FLAG_CHANGED, "old_value", "oldValue"); 133 addRenameEntry(map, JdkTypeIDsPreJdk11.INT_FLAG_CHANGED, "new_value", "newValue"); 134 addRenameEntry(map, JdkTypeIDsPreJdk11.UINT_FLAG_CHANGED, "old_value", "oldValue"); 135 addRenameEntry(map, JdkTypeIDsPreJdk11.UINT_FLAG_CHANGED, "new_value", "newValue"); 136 addRenameEntry(map, JdkTypeIDsPreJdk11.LONG_FLAG_CHANGED, "old_value", "oldValue"); 137 addRenameEntry(map, JdkTypeIDsPreJdk11.LONG_FLAG_CHANGED, "new_value", "newValue"); 138 addRenameEntry(map, JdkTypeIDsPreJdk11.ULONG_FLAG_CHANGED, "old_value", "oldValue"); 139 addRenameEntry(map, JdkTypeIDsPreJdk11.ULONG_FLAG_CHANGED, "new_value", "newValue"); 140 addRenameEntry(map, JdkTypeIDsPreJdk11.DOUBLE_FLAG_CHANGED, "old_value", "oldValue"); 141 addRenameEntry(map, JdkTypeIDsPreJdk11.DOUBLE_FLAG_CHANGED, "new_value", "newValue"); 142 addRenameEntry(map, JdkTypeIDsPreJdk11.BOOLEAN_FLAG_CHANGED, "old_value", "oldValue"); 143 addRenameEntry(map, JdkTypeIDsPreJdk11.BOOLEAN_FLAG_CHANGED, "new_value", "newValue"); 144 addRenameEntry(map, JdkTypeIDsPreJdk11.STRING_FLAG_CHANGED, "old_value", "oldValue"); 145 addRenameEntry(map, JdkTypeIDsPreJdk11.STRING_FLAG_CHANGED, "new_value", "newValue"); 146 addRenameEntry(map, JdkTypeIDsPreJdk11.GC_DETAILED_EVACUATION_INFO, "allocRegionsUsedBefore", 147 "allocationRegionsUsedBefore"); 148 addRenameEntry(map, JdkTypeIDsPreJdk11.GC_DETAILED_EVACUATION_INFO, "allocRegionsUsedAfter", 149 "allocationRegionsUsedAfter"); 150 addRenameEntry(map, JdkTypeIDsPreJdk11.SWEEP_CODE_CACHE, "sweepIndex", "sweepId"); 151 addRenameEntry(map, JdkTypeIDsPreJdk11.ALLOC_INSIDE_TLAB, "class", 152 JdkAttributes.ALLOCATION_CLASS.getIdentifier()); 153 addRenameEntry(map, JdkTypeIDsPreJdk11.ALLOC_OUTSIDE_TLAB, "class", 154 JdkAttributes.ALLOCATION_CLASS.getIdentifier()); 155 addRenameEntry(map, JdkTypeIDsPreJdk11.OBJECT_COUNT, "class", JdkAttributes.OBJECT_CLASS.getIdentifier()); 156 addRenameEntry(map, JdkTypeIDsPreJdk11.COMPILER_PHASE, "compileID", 157 JdkAttributes.COMPILER_COMPILATION_ID.getIdentifier()); 158 addRenameEntry(map, JdkTypeIDsPreJdk11.COMPILATION, "compileID", 159 JdkAttributes.COMPILER_COMPILATION_ID.getIdentifier()); 160 addRenameEntry(map, JdkTypeIDsPreJdk11.COMPILER_FAILURE, "compileID", 161 JdkAttributes.COMPILER_COMPILATION_ID.getIdentifier()); 162 addRenameEntry(map, JdkTypeIDsPreJdk11.COMPILER_FAILURE, "failure", 163 JdkAttributes.COMPILER_FAILED_MESSAGE.getIdentifier()); 164 addRenameEntry(map, JdkTypeIDsPreJdk11.GC_DETAILED_OBJECT_COUNT_AFTER_GC, "class", 165 JdkAttributes.OBJECT_CLASS.getIdentifier()); 166 return map; 167 } 168 169 private static void addRenameEntry( 170 Map<String, Map<String, String>> renameMap, String eventId, String pre9AttrId, String attrId) { 171 Map<String, String> attrMap = renameMap.get(eventId); 172 if (attrMap == null) { 173 attrMap = new HashMap<>(); 174 renameMap.put(eventId, attrMap); 175 } 176 attrMap.put(pre9AttrId, attrId); 177 } 178 179 SettingsTransformer(IEventSinkFactory sinkFactory, String label, String[] category, String description, 180 List<ValueField> dataStructure) { 181 for (int i = 0; i < dataStructure.size(); i++) { 182 ValueField vf = dataStructure.get(i); 183 if (vf.matches(JfrAttributes.END_TIME)) { 184 endTimeIndex = i; 185 } else if (vf.matches(SyntheticAttributeExtension.REC_SETTING_EVENT_ID_ATTRIBUTE)) { 186 typeIndex = i; 187 } else if (vf.matches(REC_SETTINGS_ATTR_ENABLED)) { 188 enabledIndex = i; 189 } else if (vf.matches(REC_SETTINGS_ATTR_STACKTRACE)) { 190 stacktraceIndex = i; 191 } else if (vf.matches(REC_SETTINGS_ATTR_THRESHOLD)) { 192 thresholdIndex = i; 193 } else if (vf.matches(REC_SETTINGS_ATTR_PERIOD)) { 194 periodIndex = i; 195 } 196 } 197 if (endTimeIndex >= 0) { 198 sink = sinkFactory.create(JdkTypeIDs.RECORDING_SETTING, label, category, description, FIELDS); 199 } else { 200 sink = sinkFactory.create(JdkTypeIDs.RECORDING_SETTING, label, category, description, dataStructure); 201 } 202 } 203 204 boolean isValid() { 205 return endTimeIndex >= 0 && typeIndex >= 0 && enabledIndex >= 0 && stacktraceIndex >= 0 && thresholdIndex >= 0 206 && periodIndex >= 0; 207 } 208 209 boolean isValidV1() { 210 return typeIndex >= 0; 211 } 212 213 @Override 214 public void addEvent(Object[] values) { 215 LabeledIdentifier type = (LabeledIdentifier) values[typeIndex]; 216 if (type != null) { 217 if (JdkTypeIDsPreJdk11.needTransform(type.getInterfaceId())) { 218 type = new LabeledIdentifier(JdkTypeIDsPreJdk11.translate(type.getInterfaceId()), 219 type.getImplementationId(), type.getName(), type.getDeclaredDescription()); 220 } 221 if (endTimeIndex < 0) { 222 values[typeIndex] = type; 223 sink.addEvent(values); 224 return; 225 } 226 } 227 Object startTime = values[endTimeIndex]; 228 229 addSettingEvent(startTime, type, REC_SETTING_NAME_ENABLED, values[enabledIndex]); 230 addSettingEvent(startTime, type, REC_SETTING_NAME_STACKTRACE, values[stacktraceIndex]); 231 addThresholdSettingEvent(startTime, type, (IQuantity) values[thresholdIndex]); 232 addPeriodSettingEvent(startTime, type, (IQuantity) values[periodIndex]); 233 } 234 235 private boolean addThresholdSettingEvent(Object startTime, LabeledIdentifier type, IQuantity quantity) { 236 // Remove thresholds with Long.MIN_VALUE ns duration as these are just padding for 237 // event types that cannot have thresholds. (At least JDK 7u75 used Long.MAX_VALUE.) 238 if (quantity != null) { 239 long numQuantity = quantity.longValue(); 240 if ((numQuantity != Long.MIN_VALUE) && (numQuantity != Long.MAX_VALUE)) { 241 addSettingEvent(startTime, type, REC_SETTING_NAME_THRESHOLD, quantity.persistableString()); 242 } 243 } 244 return false; 245 } 263 reusableArray[1] = type; 264 reusableArray[2] = settingName; 265 reusableArray[3] = settingValue == null ? null : settingValue.toString(); 266 sink.addEvent(reusableArray); 267 } 268 269 /* 270 * FIXME: Weird to explicitly wrap when the parser does exactly that. 271 * 272 * This class should be refactored into a parser extension although this may require a change to 273 * the API by adding priorities so that type transformation occurs before synthetic attributes 274 * are added. 275 */ 276 static IEventSinkFactory wrapSinkFactory(final IEventSinkFactory subFactory) { 277 return new IEventSinkFactory() { 278 279 @Override 280 public IEventSink create( 281 String identifier, String label, String[] category, String description, 282 List<ValueField> dataStructure) { 283 boolean needsTransform = JdkTypeIDsPreJdk11.needTransform(identifier); 284 if (JdkTypeIDsPreJdk11.RECORDING_SETTING.equals(identifier) || 285 (needsTransform && 286 JdkTypeIDs.RECORDING_SETTING.equals(JdkTypeIDsPreJdk11.translate(identifier)))) { 287 SettingsTransformer st = new SettingsTransformer(subFactory, label, category, description, 288 dataStructure); 289 if (st.isValid() || (needsTransform && st.isValidV1())) { 290 return st; 291 } else { 292 // FIXME: Avoid System.err.println 293 System.err 294 .println("Cannot create SettingsTransformer from fields: " + dataStructure.toString()); //$NON-NLS-1$ 295 } 296 } else if (JdkTypeIDsPreJdk11.RECORDINGS.equals(identifier)) { 297 /* 298 * NOTE: Renaming 'duration' and 'startTime' attributes for JDK 8 'Recording' 299 * events so that they won't conflict with general attributes with the same 300 * names in JDK 9+ recordings. 301 */ 302 ValueField[] struct = new ValueField[dataStructure.size()]; 303 for (int i = 0; i < struct.length; i++) { 304 ValueField vf = dataStructure.get(i); 305 if (vf.matches(JfrAttributes.START_TIME)) { 306 vf = new ValueField(JdkAttributes.RECORDING_START); 307 } else if (vf.matches(JfrAttributes.DURATION)) { 308 vf = new ValueField(JdkAttributes.RECORDING_DURATION); 309 } 310 struct[i] = vf; 311 } 312 return subFactory.create(JdkTypeIDs.RECORDINGS, label, category, description, 313 Arrays.asList(struct)); 314 } else if (JdkTypeIDsPreJdk11.CODE_CACHE_STATISTICS.equals(identifier)) { 315 for (int i = 0; i < dataStructure.size(); i++) { 316 if (UNALLOCATED_CAPACITY_FIELD_ID.equals(dataStructure.get(i).getIdentifier())) { 317 return new FixCodeCacheSink(i, subFactory.create(JdkTypeIDsPreJdk11.translate(identifier), 318 label, category, description, dataStructure)); 319 } 320 } 321 } 322 return subFactory.create(JdkTypeIDsPreJdk11.translate(identifier), label, category, description, 323 translate(identifier, dataStructure)); 324 } 325 326 private List<ValueField> translate(String identifier, List<ValueField> dataStructure) { 327 Map<String, String> attrMap = attributeRenameMap.get(identifier); 328 if (attrMap == null) { 329 return dataStructure; 330 } 331 List<ValueField> renamedDataStructure = new ArrayList<>(); 332 for (ValueField vf : dataStructure) { 333 String renamedId = attrMap.get(vf.getIdentifier()); 334 if (renamedId == null) { 335 renamedDataStructure.add(vf); 336 } else { 337 renamedDataStructure 338 .add(new ValueField(renamedId, vf.getName(), vf.getDescription(), vf.getContentType())); 339 } 340 } 341 return renamedDataStructure; 342 } |