author | cito |
Thu, 28 Nov 2019 18:30:18 +0100 | |
changeset 59312 | 43eee1237934 |
parent 58863 | c16ac7a2eba4 |
permissions | -rw-r--r-- |
50113 | 1 |
/* |
58863 | 2 |
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. |
50113 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package jdk.jfr.internal; |
|
27 |
||
28 |
import static java.util.concurrent.TimeUnit.MICROSECONDS; |
|
29 |
import static java.util.concurrent.TimeUnit.MILLISECONDS; |
|
30 |
import static java.util.concurrent.TimeUnit.NANOSECONDS; |
|
31 |
import static java.util.concurrent.TimeUnit.SECONDS; |
|
32 |
||
33 |
import java.io.FileOutputStream; |
|
34 |
import java.io.FileWriter; |
|
35 |
import java.io.IOException; |
|
36 |
import java.io.PrintWriter; |
|
37 |
import java.io.RandomAccessFile; |
|
38 |
import java.lang.annotation.Annotation; |
|
39 |
import java.lang.annotation.Repeatable; |
|
40 |
import java.lang.reflect.Field; |
|
41 |
import java.lang.reflect.InvocationTargetException; |
|
42 |
import java.lang.reflect.Method; |
|
43 |
import java.lang.reflect.Modifier; |
|
44 |
import java.nio.file.Path; |
|
45 |
import java.time.Duration; |
|
58863 | 46 |
import java.time.Instant; |
50745 | 47 |
import java.time.LocalDateTime; |
59312
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
48 |
import java.time.temporal.ChronoUnit; |
50113 | 49 |
import java.util.ArrayList; |
50 |
import java.util.Arrays; |
|
51 |
import java.util.Collections; |
|
52 |
import java.util.HashMap; |
|
53 |
import java.util.List; |
|
54 |
import java.util.Map; |
|
55 |
import java.util.Objects; |
|
56 |
||
57 |
import jdk.internal.org.objectweb.asm.ClassReader; |
|
58 |
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; |
|
59 |
import jdk.jfr.Event; |
|
60 |
import jdk.jfr.FlightRecorderPermission; |
|
50745 | 61 |
import jdk.jfr.Recording; |
50113 | 62 |
import jdk.jfr.RecordingState; |
63 |
import jdk.jfr.internal.handlers.EventHandler; |
|
64 |
import jdk.jfr.internal.settings.PeriodSetting; |
|
65 |
import jdk.jfr.internal.settings.StackTraceSetting; |
|
66 |
import jdk.jfr.internal.settings.ThresholdSetting; |
|
67 |
||
68 |
public final class Utils { |
|
69 |
||
58863 | 70 |
private static final Object flushObject = new Object(); |
52901
3ba9ff4d4aaf
8212232: Wrong metadata for the configuration of the cutoff for old object sample events
egahlin
parents:
52850
diff
changeset
|
71 |
private static final String INFINITY = "infinity"; |
50113 | 72 |
public static final String EVENTS_PACKAGE_NAME = "jdk.jfr.events"; |
73 |
public static final String INSTRUMENT_PACKAGE_NAME = "jdk.jfr.internal.instrument"; |
|
74 |
public static final String HANDLERS_PACKAGE_NAME = "jdk.jfr.internal.handlers"; |
|
75 |
public static final String REGISTER_EVENT = "registerEvent"; |
|
76 |
public static final String ACCESS_FLIGHT_RECORDER = "accessFlightRecorder"; |
|
58863 | 77 |
private final static String LEGACY_EVENT_NAME_PREFIX = "com.oracle.jdk."; |
50113 | 78 |
|
58863 | 79 |
private static Boolean SAVE_GENERATED; |
80 |
||
50113 | 81 |
|
59312
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
82 |
private static final Duration MICRO_SECOND = Duration.ofNanos(1_000); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
83 |
private static final Duration SECOND = Duration.ofSeconds(1); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
84 |
private static final Duration MINUTE = Duration.ofMinutes(1); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
85 |
private static final Duration HOUR = Duration.ofHours(1); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
86 |
private static final Duration DAY = Duration.ofDays(1); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
87 |
private static final int NANO_SIGNIFICANT_FIGURES = 9; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
88 |
private static final int MILL_SIGNIFICANT_FIGURES = 3; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
89 |
private static final int DISPLAY_NANO_DIGIT = 3; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
90 |
private static final int BASE = 10; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
91 |
|
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
92 |
|
50113 | 93 |
public static void checkAccessFlightRecorder() throws SecurityException { |
94 |
SecurityManager sm = System.getSecurityManager(); |
|
95 |
if (sm != null) { |
|
96 |
sm.checkPermission(new FlightRecorderPermission(ACCESS_FLIGHT_RECORDER)); |
|
97 |
} |
|
98 |
} |
|
99 |
||
100 |
public static void checkRegisterPermission() throws SecurityException { |
|
101 |
SecurityManager sm = System.getSecurityManager(); |
|
102 |
if (sm != null) { |
|
103 |
sm.checkPermission(new FlightRecorderPermission(REGISTER_EVENT)); |
|
104 |
} |
|
105 |
} |
|
106 |
||
107 |
private static enum TimespanUnit { |
|
108 |
NANOSECONDS("ns", 1000), MICROSECONDS("us", 1000), MILLISECONDS("ms", 1000), SECONDS("s", 60), MINUTES("m", 60), HOURS("h", 24), DAYS("d", 7); |
|
109 |
||
110 |
final String text; |
|
111 |
final long amount; |
|
112 |
||
113 |
TimespanUnit(String unit, long amount) { |
|
114 |
this.text = unit; |
|
115 |
this.amount = amount; |
|
116 |
} |
|
117 |
} |
|
118 |
||
53013 | 119 |
// Tjis method can't handle Long.MIN_VALUE because absolute value is negative |
120 |
private static String formatDataAmount(String formatter, long amount) { |
|
121 |
int exp = (int) (Math.log(Math.abs(amount)) / Math.log(1024)); |
|
122 |
char unitPrefix = "kMGTPE".charAt(exp - 1); |
|
123 |
return String.format(formatter, amount / Math.pow(1024, exp), unitPrefix); |
|
124 |
} |
|
125 |
||
126 |
public static String formatBytesCompact(long bytes) { |
|
127 |
if (bytes < 1024) { |
|
128 |
return String.valueOf(bytes); |
|
52850 | 129 |
} |
53013 | 130 |
return formatDataAmount("%.1f%cB", bytes); |
131 |
} |
|
132 |
||
133 |
public static String formatBits(long bits) { |
|
134 |
if (bits == 1 || bits == -1) { |
|
135 |
return bits + " bit"; |
|
136 |
} |
|
137 |
if (bits < 1024 && bits > -1024) { |
|
138 |
return bits + " bits"; |
|
139 |
} |
|
140 |
return formatDataAmount("%.1f %cbit", bits); |
|
141 |
} |
|
142 |
||
143 |
public static String formatBytes(long bytes) { |
|
144 |
if (bytes == 1 || bytes == -1) { |
|
145 |
return bytes + " byte"; |
|
146 |
} |
|
147 |
if (bytes < 1024 && bytes > -1024) { |
|
50113 | 148 |
return bytes + " bytes"; |
149 |
} |
|
53013 | 150 |
return formatDataAmount("%.1f %cB", bytes); |
50113 | 151 |
} |
152 |
||
53013 | 153 |
public static String formatBytesPerSecond(long bytes) { |
154 |
if (bytes < 1024 && bytes > -1024) { |
|
155 |
return bytes + " byte/s"; |
|
156 |
} |
|
157 |
return formatDataAmount("%.1f %cB/s", bytes); |
|
158 |
} |
|
159 |
||
160 |
public static String formatBitsPerSecond(long bits) { |
|
161 |
if (bits < 1024 && bits > -1024) { |
|
162 |
return bits + " bps"; |
|
163 |
} |
|
164 |
return formatDataAmount("%.1f %cbps", bits); |
|
165 |
} |
|
50113 | 166 |
public static String formatTimespan(Duration dValue, String separation) { |
167 |
if (dValue == null) { |
|
168 |
return "0"; |
|
169 |
} |
|
170 |
long value = dValue.toNanos(); |
|
171 |
TimespanUnit result = TimespanUnit.NANOSECONDS; |
|
172 |
for (TimespanUnit unit : TimespanUnit.values()) { |
|
173 |
result = unit; |
|
174 |
long amount = unit.amount; |
|
175 |
if (result == TimespanUnit.DAYS || value < amount || value % amount != 0) { |
|
176 |
break; |
|
177 |
} |
|
178 |
value /= amount; |
|
179 |
} |
|
180 |
return String.format("%d%s%s", value, separation, result.text); |
|
181 |
} |
|
182 |
||
52901
3ba9ff4d4aaf
8212232: Wrong metadata for the configuration of the cutoff for old object sample events
egahlin
parents:
52850
diff
changeset
|
183 |
public static long parseTimespanWithInfinity(String s) { |
3ba9ff4d4aaf
8212232: Wrong metadata for the configuration of the cutoff for old object sample events
egahlin
parents:
52850
diff
changeset
|
184 |
if (INFINITY.equals(s)) { |
3ba9ff4d4aaf
8212232: Wrong metadata for the configuration of the cutoff for old object sample events
egahlin
parents:
52850
diff
changeset
|
185 |
return Long.MAX_VALUE; |
3ba9ff4d4aaf
8212232: Wrong metadata for the configuration of the cutoff for old object sample events
egahlin
parents:
52850
diff
changeset
|
186 |
} |
3ba9ff4d4aaf
8212232: Wrong metadata for the configuration of the cutoff for old object sample events
egahlin
parents:
52850
diff
changeset
|
187 |
return parseTimespan(s); |
3ba9ff4d4aaf
8212232: Wrong metadata for the configuration of the cutoff for old object sample events
egahlin
parents:
52850
diff
changeset
|
188 |
} |
3ba9ff4d4aaf
8212232: Wrong metadata for the configuration of the cutoff for old object sample events
egahlin
parents:
52850
diff
changeset
|
189 |
|
50113 | 190 |
public static long parseTimespan(String s) { |
191 |
if (s.endsWith("ns")) { |
|
192 |
return Long.parseLong(s.substring(0, s.length() - 2).trim()); |
|
193 |
} |
|
194 |
if (s.endsWith("us")) { |
|
195 |
return NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 2).trim()), MICROSECONDS); |
|
196 |
} |
|
197 |
if (s.endsWith("ms")) { |
|
198 |
return NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 2).trim()), MILLISECONDS); |
|
199 |
} |
|
200 |
if (s.endsWith("s")) { |
|
201 |
return NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), SECONDS); |
|
202 |
} |
|
203 |
if (s.endsWith("m")) { |
|
204 |
return 60 * NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), SECONDS); |
|
205 |
} |
|
206 |
if (s.endsWith("h")) { |
|
207 |
return 60 * 60 * NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), SECONDS); |
|
208 |
} |
|
209 |
if (s.endsWith("d")) { |
|
210 |
return 24 * 60 * 60 * NANOSECONDS.convert(Long.parseLong(s.substring(0, s.length() - 1).trim()), SECONDS); |
|
211 |
} |
|
212 |
||
213 |
try { |
|
214 |
Long.parseLong(s); |
|
215 |
} catch (NumberFormatException nfe) { |
|
216 |
throw new NumberFormatException("'" + s + "' is not a valid timespan. Shoule be numeric value followed by a unit, i.e. 20 ms. Valid units are ns, us, s, m, h and d."); |
|
217 |
} |
|
218 |
// Only accept values with units |
|
219 |
throw new NumberFormatException("Timespan + '" + s + "' is missing unit. Valid units are ns, us, s, m, h and d."); |
|
220 |
} |
|
221 |
||
222 |
/** |
|
223 |
* Return all annotations as they are visible in the source code |
|
224 |
* |
|
225 |
* @param clazz class to return annotations from |
|
226 |
* |
|
227 |
* @return list of annotation |
|
228 |
* |
|
229 |
*/ |
|
230 |
static List<Annotation> getAnnotations(Class<?> clazz) { |
|
231 |
List<Annotation> annos = new ArrayList<>(); |
|
232 |
for (Annotation a : clazz.getAnnotations()) { |
|
233 |
annos.addAll(getAnnotation(a)); |
|
234 |
} |
|
235 |
return annos; |
|
236 |
} |
|
237 |
||
238 |
private static List<? extends Annotation> getAnnotation(Annotation a) { |
|
239 |
Class<?> annotated = a.annotationType(); |
|
240 |
Method valueMethod = getValueMethod(annotated); |
|
241 |
if (valueMethod != null) { |
|
242 |
Class<?> returnType = valueMethod.getReturnType(); |
|
243 |
if (returnType.isArray()) { |
|
244 |
Class<?> candidate = returnType.getComponentType(); |
|
245 |
Repeatable r = candidate.getAnnotation(Repeatable.class); |
|
246 |
if (r != null) { |
|
247 |
Class<?> repeatClass = r.value(); |
|
248 |
if (annotated == repeatClass) { |
|
249 |
return getAnnotationValues(a, valueMethod); |
|
250 |
} |
|
251 |
} |
|
252 |
} |
|
253 |
} |
|
254 |
List<Annotation> annos = new ArrayList<>(); |
|
255 |
annos.add(a); |
|
256 |
return annos; |
|
257 |
} |
|
258 |
||
259 |
static boolean isAfter(RecordingState stateToTest, RecordingState b) { |
|
260 |
return stateToTest.ordinal() > b.ordinal(); |
|
261 |
} |
|
262 |
||
263 |
static boolean isBefore(RecordingState stateToTest, RecordingState b) { |
|
264 |
return stateToTest.ordinal() < b.ordinal(); |
|
265 |
} |
|
266 |
||
267 |
static boolean isState(RecordingState stateToTest, RecordingState... states) { |
|
268 |
for (RecordingState s : states) { |
|
269 |
if (s == stateToTest) { |
|
270 |
return true; |
|
271 |
} |
|
272 |
} |
|
273 |
return false; |
|
274 |
} |
|
275 |
||
276 |
private static List<Annotation> getAnnotationValues(Annotation a, Method valueMethod) { |
|
277 |
try { |
|
278 |
return Arrays.asList((Annotation[]) valueMethod.invoke(a, new Object[0])); |
|
279 |
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { |
|
280 |
return new ArrayList<>(); |
|
281 |
} |
|
282 |
} |
|
283 |
||
284 |
private static Method getValueMethod(Class<?> annotated) { |
|
285 |
try { |
|
286 |
return annotated.getMethod("value", new Class<?>[0]); |
|
287 |
} catch (NoSuchMethodException e) { |
|
288 |
return null; |
|
289 |
} |
|
290 |
} |
|
291 |
||
292 |
public static void touch(Path dumpFile) throws IOException { |
|
293 |
RandomAccessFile raf = new RandomAccessFile(dumpFile.toFile(), "rw"); |
|
294 |
raf.close(); |
|
295 |
} |
|
296 |
||
297 |
public static Class<?> unboxType(Class<?> t) { |
|
298 |
if (t == Integer.class) { |
|
299 |
return int.class; |
|
300 |
} |
|
301 |
if (t == Long.class) { |
|
302 |
return long.class; |
|
303 |
} |
|
304 |
if (t == Float.class) { |
|
305 |
return float.class; |
|
306 |
} |
|
307 |
if (t == Double.class) { |
|
308 |
return double.class; |
|
309 |
} |
|
310 |
if (t == Byte.class) { |
|
311 |
return byte.class; |
|
312 |
} |
|
313 |
if (t == Short.class) { |
|
314 |
return short.class; |
|
315 |
} |
|
316 |
if (t == Boolean.class) { |
|
317 |
return boolean.class; |
|
318 |
} |
|
319 |
if (t == Character.class) { |
|
320 |
return char.class; |
|
321 |
} |
|
322 |
return t; |
|
323 |
} |
|
324 |
||
325 |
static long nanosToTicks(long nanos) { |
|
326 |
return (long) (nanos * JVM.getJVM().getTimeConversionFactor()); |
|
327 |
} |
|
328 |
||
52334
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
329 |
static synchronized EventHandler getHandler(Class<? extends jdk.internal.event.Event> eventClass) { |
50113 | 330 |
Utils.ensureValidEventSubclass(eventClass); |
331 |
try { |
|
332 |
Field f = eventClass.getDeclaredField(EventInstrumentation.FIELD_EVENT_HANDLER); |
|
333 |
SecuritySupport.setAccessible(f); |
|
334 |
return (EventHandler) f.get(null); |
|
335 |
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) { |
|
336 |
throw new InternalError("Could not access event handler"); |
|
337 |
} |
|
338 |
} |
|
339 |
||
52334
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
340 |
static synchronized void setHandler(Class<? extends jdk.internal.event.Event> eventClass, EventHandler handler) { |
50113 | 341 |
Utils.ensureValidEventSubclass(eventClass); |
342 |
try { |
|
343 |
Field field = eventClass.getDeclaredField(EventInstrumentation.FIELD_EVENT_HANDLER); |
|
344 |
SecuritySupport.setAccessible(field); |
|
345 |
field.set(null, handler); |
|
346 |
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) { |
|
347 |
throw new InternalError("Could not access event handler"); |
|
348 |
} |
|
349 |
} |
|
350 |
||
351 |
public static Map<String, String> sanitizeNullFreeStringMap(Map<String, String> settings) { |
|
352 |
HashMap<String, String> map = new HashMap<>(settings.size()); |
|
353 |
for (Map.Entry<String, String> e : settings.entrySet()) { |
|
354 |
String key = e.getKey(); |
|
355 |
if (key == null) { |
|
356 |
throw new NullPointerException("Null key is not allowed in map"); |
|
357 |
} |
|
358 |
String value = e.getValue(); |
|
359 |
if (value == null) { |
|
360 |
throw new NullPointerException("Null value is not allowed in map"); |
|
361 |
} |
|
362 |
map.put(key, value); |
|
363 |
} |
|
364 |
return map; |
|
365 |
} |
|
366 |
||
367 |
public static <T> List<T> sanitizeNullFreeList(List<T> elements, Class<T> clazz) { |
|
368 |
List<T> sanitized = new ArrayList<>(elements.size()); |
|
369 |
for (T element : elements) { |
|
370 |
if (element == null) { |
|
371 |
throw new NullPointerException("Null is not an allowed element in list"); |
|
372 |
} |
|
373 |
if (element.getClass() != clazz) { |
|
374 |
throw new ClassCastException(); |
|
375 |
} |
|
376 |
sanitized.add(element); |
|
377 |
} |
|
378 |
return sanitized; |
|
379 |
} |
|
380 |
||
381 |
static List<Field> getVisibleEventFields(Class<?> clazz) { |
|
382 |
Utils.ensureValidEventSubclass(clazz); |
|
383 |
List<Field> fields = new ArrayList<>(); |
|
52334
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
384 |
for (Class<?> c = clazz; c != jdk.internal.event.Event.class; c = c.getSuperclass()) { |
50113 | 385 |
for (Field field : c.getDeclaredFields()) { |
386 |
// skip private field in base classes |
|
387 |
if (c == clazz || !Modifier.isPrivate(field.getModifiers())) { |
|
388 |
fields.add(field); |
|
389 |
} |
|
390 |
} |
|
391 |
} |
|
392 |
return fields; |
|
393 |
} |
|
394 |
||
395 |
public static void ensureValidEventSubclass(Class<?> eventClass) { |
|
52334
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
396 |
if (jdk.internal.event.Event.class.isAssignableFrom(eventClass) && Modifier.isAbstract(eventClass.getModifiers())) { |
50113 | 397 |
throw new IllegalArgumentException("Abstract event classes are not allowed"); |
398 |
} |
|
52334
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
399 |
if (eventClass == Event.class || eventClass == jdk.internal.event.Event.class || !jdk.internal.event.Event.class.isAssignableFrom(eventClass)) { |
50113 | 400 |
throw new IllegalArgumentException("Must be a subclass to " + Event.class.getName()); |
401 |
} |
|
402 |
} |
|
403 |
||
404 |
public static void writeGeneratedASM(String className, byte[] bytes) { |
|
405 |
if (SAVE_GENERATED == null) { |
|
406 |
// We can't calculate value statically because it will force |
|
407 |
// initialization of SecuritySupport, which cause |
|
408 |
// UnsatisfiedLinkedError on JDK 8 or non-Oracle JDKs |
|
409 |
SAVE_GENERATED = SecuritySupport.getBooleanProperty("jfr.save.generated.asm"); |
|
410 |
} |
|
411 |
if (SAVE_GENERATED) { |
|
412 |
try { |
|
413 |
try (FileOutputStream fos = new FileOutputStream(className + ".class")) { |
|
414 |
fos.write(bytes); |
|
415 |
} |
|
416 |
||
417 |
try (FileWriter fw = new FileWriter(className + ".asm"); PrintWriter pw = new PrintWriter(fw)) { |
|
418 |
ClassReader cr = new ClassReader(bytes); |
|
419 |
CheckClassAdapter.verify(cr, true, pw); |
|
420 |
} |
|
421 |
Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.INFO, "Instrumented code saved to " + className + ".class and .asm"); |
|
422 |
} catch (IOException e) { |
|
423 |
Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.INFO, "Could not save instrumented code, for " + className + ".class and .asm"); |
|
424 |
} |
|
425 |
} |
|
426 |
} |
|
427 |
||
52334
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
428 |
public static void ensureInitialized(Class<? extends jdk.internal.event.Event> eventClass) { |
50113 | 429 |
SecuritySupport.ensureClassIsInitialized(eventClass); |
430 |
} |
|
431 |
||
432 |
public static Object makePrimitiveArray(String typeName, List<Object> values) { |
|
433 |
int length = values.size(); |
|
434 |
switch (typeName) { |
|
435 |
case "int": |
|
436 |
int[] ints = new int[length]; |
|
437 |
for (int i = 0; i < length; i++) { |
|
438 |
ints[i] = (int) values.get(i); |
|
439 |
} |
|
440 |
return ints; |
|
441 |
case "long": |
|
442 |
long[] longs = new long[length]; |
|
443 |
for (int i = 0; i < length; i++) { |
|
444 |
longs[i] = (long) values.get(i); |
|
445 |
} |
|
446 |
return longs; |
|
447 |
||
448 |
case "float": |
|
449 |
float[] floats = new float[length]; |
|
450 |
for (int i = 0; i < length; i++) { |
|
451 |
floats[i] = (float) values.get(i); |
|
452 |
} |
|
453 |
return floats; |
|
454 |
||
455 |
case "double": |
|
456 |
double[] doubles = new double[length]; |
|
457 |
for (int i = 0; i < length; i++) { |
|
458 |
doubles[i] = (double) values.get(i); |
|
459 |
} |
|
460 |
return doubles; |
|
461 |
||
462 |
case "short": |
|
463 |
short[] shorts = new short[length]; |
|
464 |
for (int i = 0; i < length; i++) { |
|
465 |
shorts[i] = (short) values.get(i); |
|
466 |
} |
|
467 |
return shorts; |
|
468 |
case "char": |
|
469 |
char[] chars = new char[length]; |
|
470 |
for (int i = 0; i < length; i++) { |
|
471 |
chars[i] = (char) values.get(i); |
|
472 |
} |
|
473 |
return chars; |
|
474 |
case "byte": |
|
475 |
byte[] bytes = new byte[length]; |
|
476 |
for (int i = 0; i < length; i++) { |
|
477 |
bytes[i] = (byte) values.get(i); |
|
478 |
} |
|
479 |
return bytes; |
|
480 |
case "boolean": |
|
481 |
boolean[] booleans = new boolean[length]; |
|
482 |
for (int i = 0; i < length; i++) { |
|
483 |
booleans[i] = (boolean) values.get(i); |
|
484 |
} |
|
485 |
return booleans; |
|
486 |
case "java.lang.String": |
|
487 |
String[] strings = new String[length]; |
|
488 |
for (int i = 0; i < length; i++) { |
|
489 |
strings[i] = (String) values.get(i); |
|
490 |
} |
|
491 |
return strings; |
|
492 |
} |
|
493 |
return null; |
|
494 |
} |
|
495 |
||
496 |
public static boolean isSettingVisible(Control c, boolean hasEventHook) { |
|
497 |
if (c instanceof ThresholdSetting) { |
|
498 |
return !hasEventHook; |
|
499 |
} |
|
500 |
if (c instanceof PeriodSetting) { |
|
501 |
return hasEventHook; |
|
502 |
} |
|
503 |
if (c instanceof StackTraceSetting) { |
|
504 |
return !hasEventHook; |
|
505 |
} |
|
506 |
return true; |
|
507 |
} |
|
508 |
||
509 |
public static boolean isSettingVisible(long typeId, boolean hasEventHook) { |
|
510 |
if (ThresholdSetting.isType(typeId)) { |
|
511 |
return !hasEventHook; |
|
512 |
} |
|
513 |
if (PeriodSetting.isType(typeId)) { |
|
514 |
return hasEventHook; |
|
515 |
} |
|
516 |
if (StackTraceSetting.isType(typeId)) { |
|
517 |
return !hasEventHook; |
|
518 |
} |
|
519 |
return true; |
|
520 |
} |
|
521 |
||
522 |
public static Type getValidType(Class<?> type, String name) { |
|
523 |
Objects.requireNonNull(type, "Null is not a valid type for value descriptor " + name); |
|
524 |
if (type.isArray()) { |
|
525 |
type = type.getComponentType(); |
|
526 |
if (type != String.class && !type.isPrimitive()) { |
|
527 |
throw new IllegalArgumentException("Only arrays of primitives and Strings are allowed"); |
|
528 |
} |
|
529 |
} |
|
530 |
||
531 |
Type knownType = Type.getKnownType(type); |
|
532 |
if (knownType == null || knownType == Type.STACK_TRACE) { |
|
533 |
throw new IllegalArgumentException("Only primitive types, java.lang.Thread, java.lang.String and java.lang.Class are allowed for value descriptors. " + type.getName()); |
|
534 |
} |
|
535 |
return knownType; |
|
536 |
} |
|
537 |
||
538 |
public static <T> List<T> smallUnmodifiable(List<T> list) { |
|
539 |
if (list.isEmpty()) { |
|
540 |
return Collections.emptyList(); |
|
541 |
} |
|
542 |
if (list.size() == 1) { |
|
543 |
return Collections.singletonList(list.get(0)); |
|
544 |
} |
|
545 |
return Collections.unmodifiableList(list); |
|
546 |
} |
|
547 |
||
548 |
public static String upgradeLegacyJDKEvent(String eventName) { |
|
549 |
if (eventName.length() <= LEGACY_EVENT_NAME_PREFIX.length()) { |
|
550 |
return eventName; |
|
551 |
} |
|
552 |
if (eventName.startsWith(LEGACY_EVENT_NAME_PREFIX)) { |
|
553 |
int index = eventName.lastIndexOf("."); |
|
554 |
if (index == LEGACY_EVENT_NAME_PREFIX.length() - 1) { |
|
555 |
return Type.EVENT_NAME_PREFIX + eventName.substring(index + 1); |
|
556 |
} |
|
557 |
} |
|
558 |
return eventName; |
|
559 |
} |
|
50745 | 560 |
|
52334
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
561 |
public static void verifyMirror(Class<?> mirror, Class<?> real) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
562 |
Class<?> cMirror = Objects.requireNonNull(mirror); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
563 |
Class<?> cReal = Objects.requireNonNull(real); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
564 |
|
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
565 |
while (cReal != null) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
566 |
Map<String, Field> mirrorFields = new HashMap<>(); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
567 |
if (cMirror != null) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
568 |
for (Field f : cMirror.getDeclaredFields()) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
569 |
if (isSupportedType(f.getType())) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
570 |
mirrorFields.put(f.getName(), f); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
571 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
572 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
573 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
574 |
for (Field realField : cReal.getDeclaredFields()) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
575 |
if (isSupportedType(realField.getType())) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
576 |
String fieldName = realField.getName(); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
577 |
Field mirrorField = mirrorFields.get(fieldName); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
578 |
if (mirrorField == null) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
579 |
throw new InternalError("Missing mirror field for " + cReal.getName() + "#" + fieldName); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
580 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
581 |
if (realField.getModifiers() != mirrorField.getModifiers()) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
582 |
throw new InternalError("Incorrect modifier for mirror field "+ cMirror.getName() + "#" + fieldName); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
583 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
584 |
mirrorFields.remove(fieldName); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
585 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
586 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
587 |
if (!mirrorFields.isEmpty()) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
588 |
throw new InternalError( |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
589 |
"Found additional fields in mirror class " + cMirror.getName() + " " + mirrorFields.keySet()); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
590 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
591 |
if (cMirror != null) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
592 |
cMirror = cMirror.getSuperclass(); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
593 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
594 |
cReal = cReal.getSuperclass(); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
595 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
596 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
597 |
|
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
598 |
private static boolean isSupportedType(Class<?> type) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
599 |
if (Modifier.isTransient(type.getModifiers()) || Modifier.isStatic(type.getModifiers())) { |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
600 |
return false; |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
601 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
602 |
return Type.isValidJavaFieldType(type.getName()); |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
603 |
} |
a181612f0715
8203629: Produce events in the JDK without a dependency on jdk.jfr
egahlin
parents:
50745
diff
changeset
|
604 |
|
50745 | 605 |
public static String makeFilename(Recording recording) { |
606 |
String pid = JVM.getJVM().getPid(); |
|
607 |
String date = Repository.REPO_DATE_FORMAT.format(LocalDateTime.now()); |
|
608 |
String idText = recording == null ? "" : "-id-" + Long.toString(recording.getId()); |
|
609 |
return "hotspot-" + "pid-" + pid + idText + "-" + date + ".jfr"; |
|
610 |
} |
|
58863 | 611 |
|
59312
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
612 |
public static String formatDuration(Duration d) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
613 |
Duration roundedDuration = roundDuration(d); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
614 |
if (roundedDuration.equals(Duration.ZERO)) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
615 |
return "0 s"; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
616 |
} else if(roundedDuration.isNegative()){ |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
617 |
return "-" + formatPositiveDuration(roundedDuration.abs()); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
618 |
} else { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
619 |
return formatPositiveDuration(roundedDuration); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
620 |
} |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
621 |
} |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
622 |
|
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
623 |
private static String formatPositiveDuration(Duration d){ |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
624 |
if (d.compareTo(MICRO_SECOND) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
625 |
// 0.000001 ms - 0.000999 ms |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
626 |
double outputMs = (double) d.toNanosPart() / 1_000_000; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
627 |
return String.format("%.6f ms", outputMs); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
628 |
} else if (d.compareTo(SECOND) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
629 |
// 0.001 ms - 999 ms |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
630 |
int valueLength = countLength(d.toNanosPart()); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
631 |
int outputDigit = NANO_SIGNIFICANT_FIGURES - valueLength; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
632 |
double outputMs = (double) d.toNanosPart() / 1_000_000; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
633 |
return String.format("%." + outputDigit + "f ms", outputMs); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
634 |
} else if (d.compareTo(MINUTE) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
635 |
// 1.00 s - 59.9 s |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
636 |
int valueLength = countLength(d.toSecondsPart()); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
637 |
int outputDigit = MILL_SIGNIFICANT_FIGURES - valueLength; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
638 |
double outputSecond = d.toSecondsPart() + (double) d.toMillisPart() / 1_000; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
639 |
return String.format("%." + outputDigit + "f s", outputSecond); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
640 |
} else if (d.compareTo(HOUR) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
641 |
// 1 m 0 s - 59 m 59 s |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
642 |
return String.format("%d m %d s", d.toMinutesPart(), d.toSecondsPart()); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
643 |
} else if (d.compareTo(DAY) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
644 |
// 1 h 0 m - 23 h 59 m |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
645 |
return String.format("%d h %d m", d.toHoursPart(), d.toMinutesPart()); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
646 |
} else { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
647 |
// 1 d 0 h - |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
648 |
return String.format("%d d %d h", d.toDaysPart(), d.toHoursPart()); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
649 |
} |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
650 |
} |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
651 |
|
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
652 |
private static int countLength(long value){ |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
653 |
return (int) Math.log10(value) + 1; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
654 |
} |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
655 |
|
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
656 |
private static Duration roundDuration(Duration d) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
657 |
if (d.equals(Duration.ZERO)) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
658 |
return d; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
659 |
} else if(d.isNegative()){ |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
660 |
Duration roundedPositiveDuration = roundPositiveDuration(d.abs()); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
661 |
return roundedPositiveDuration.negated(); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
662 |
} else { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
663 |
return roundPositiveDuration(d); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
664 |
} |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
665 |
} |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
666 |
|
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
667 |
private static Duration roundPositiveDuration(Duration d){ |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
668 |
if (d.compareTo(MICRO_SECOND) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
669 |
// No round |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
670 |
return d; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
671 |
} else if (d.compareTo(SECOND) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
672 |
// Round significant figures to three digits |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
673 |
int valueLength = countLength(d.toNanosPart()); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
674 |
int roundValue = (int) Math.pow(BASE, valueLength - DISPLAY_NANO_DIGIT); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
675 |
long roundedNanos = Math.round((double) d.toNanosPart() / roundValue) * roundValue; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
676 |
return d.truncatedTo(ChronoUnit.SECONDS).plusNanos(roundedNanos); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
677 |
} else if (d.compareTo(MINUTE) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
678 |
// Round significant figures to three digits |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
679 |
int valueLength = countLength(d.toSecondsPart()); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
680 |
int roundValue = (int) Math.pow(BASE, valueLength); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
681 |
long roundedMills = Math.round((double) d.toMillisPart() / roundValue) * roundValue; |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
682 |
return d.truncatedTo(ChronoUnit.SECONDS).plusMillis(roundedMills); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
683 |
} else if (d.compareTo(HOUR) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
684 |
// Round for more than 500 ms or less |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
685 |
return d.plusMillis(SECOND.dividedBy(2).toMillisPart()).truncatedTo(ChronoUnit.SECONDS); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
686 |
} else if (d.compareTo(DAY) < 0) { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
687 |
// Round for more than 30 seconds or less |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
688 |
return d.plusSeconds(MINUTE.dividedBy(2).toSecondsPart()).truncatedTo(ChronoUnit.MINUTES); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
689 |
} else { |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
690 |
// Round for more than 30 minutes or less |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
691 |
return d.plusMinutes(HOUR.dividedBy(2).toMinutesPart()).truncatedTo(ChronoUnit.HOURS); |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
692 |
} |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
693 |
} |
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
694 |
|
43eee1237934
8232594: Make the output of the JFR command duration more user friendly
cito
parents:
58863
diff
changeset
|
695 |
|
58863 | 696 |
public static void takeNap(long millis) { |
697 |
try { |
|
698 |
Thread.sleep(millis); |
|
699 |
} catch (InterruptedException e) { |
|
700 |
// ok |
|
701 |
} |
|
702 |
} |
|
703 |
||
704 |
public static void notifyFlush() { |
|
705 |
synchronized (flushObject) { |
|
706 |
flushObject.notifyAll(); |
|
707 |
} |
|
708 |
} |
|
709 |
||
710 |
public static void waitFlush(long timeOut) { |
|
711 |
synchronized (flushObject) { |
|
712 |
try { |
|
713 |
flushObject.wait(timeOut); |
|
714 |
} catch (InterruptedException e) { |
|
715 |
// OK |
|
716 |
} |
|
717 |
} |
|
718 |
||
719 |
} |
|
720 |
||
721 |
public static long timeToNanos(Instant timestamp) { |
|
722 |
return timestamp.getEpochSecond() * 1_000_000_000L + timestamp.getNano(); |
|
723 |
} |
|
50113 | 724 |
} |