43 import java.lang.reflect.Modifier; |
43 import java.lang.reflect.Modifier; |
44 import java.nio.file.Path; |
44 import java.nio.file.Path; |
45 import java.time.Duration; |
45 import java.time.Duration; |
46 import java.time.Instant; |
46 import java.time.Instant; |
47 import java.time.LocalDateTime; |
47 import java.time.LocalDateTime; |
|
48 import java.time.temporal.ChronoUnit; |
48 import java.util.ArrayList; |
49 import java.util.ArrayList; |
49 import java.util.Arrays; |
50 import java.util.Arrays; |
50 import java.util.Collections; |
51 import java.util.Collections; |
51 import java.util.HashMap; |
52 import java.util.HashMap; |
52 import java.util.List; |
53 import java.util.List; |
74 public static final String REGISTER_EVENT = "registerEvent"; |
75 public static final String REGISTER_EVENT = "registerEvent"; |
75 public static final String ACCESS_FLIGHT_RECORDER = "accessFlightRecorder"; |
76 public static final String ACCESS_FLIGHT_RECORDER = "accessFlightRecorder"; |
76 private final static String LEGACY_EVENT_NAME_PREFIX = "com.oracle.jdk."; |
77 private final static String LEGACY_EVENT_NAME_PREFIX = "com.oracle.jdk."; |
77 |
78 |
78 private static Boolean SAVE_GENERATED; |
79 private static Boolean SAVE_GENERATED; |
|
80 |
|
81 |
|
82 private static final Duration MICRO_SECOND = Duration.ofNanos(1_000); |
|
83 private static final Duration SECOND = Duration.ofSeconds(1); |
|
84 private static final Duration MINUTE = Duration.ofMinutes(1); |
|
85 private static final Duration HOUR = Duration.ofHours(1); |
|
86 private static final Duration DAY = Duration.ofDays(1); |
|
87 private static final int NANO_SIGNIFICANT_FIGURES = 9; |
|
88 private static final int MILL_SIGNIFICANT_FIGURES = 3; |
|
89 private static final int DISPLAY_NANO_DIGIT = 3; |
|
90 private static final int BASE = 10; |
79 |
91 |
80 |
92 |
81 public static void checkAccessFlightRecorder() throws SecurityException { |
93 public static void checkAccessFlightRecorder() throws SecurityException { |
82 SecurityManager sm = System.getSecurityManager(); |
94 SecurityManager sm = System.getSecurityManager(); |
83 if (sm != null) { |
95 if (sm != null) { |
595 String date = Repository.REPO_DATE_FORMAT.format(LocalDateTime.now()); |
607 String date = Repository.REPO_DATE_FORMAT.format(LocalDateTime.now()); |
596 String idText = recording == null ? "" : "-id-" + Long.toString(recording.getId()); |
608 String idText = recording == null ? "" : "-id-" + Long.toString(recording.getId()); |
597 return "hotspot-" + "pid-" + pid + idText + "-" + date + ".jfr"; |
609 return "hotspot-" + "pid-" + pid + idText + "-" + date + ".jfr"; |
598 } |
610 } |
599 |
611 |
|
612 public static String formatDuration(Duration d) { |
|
613 Duration roundedDuration = roundDuration(d); |
|
614 if (roundedDuration.equals(Duration.ZERO)) { |
|
615 return "0 s"; |
|
616 } else if(roundedDuration.isNegative()){ |
|
617 return "-" + formatPositiveDuration(roundedDuration.abs()); |
|
618 } else { |
|
619 return formatPositiveDuration(roundedDuration); |
|
620 } |
|
621 } |
|
622 |
|
623 private static String formatPositiveDuration(Duration d){ |
|
624 if (d.compareTo(MICRO_SECOND) < 0) { |
|
625 // 0.000001 ms - 0.000999 ms |
|
626 double outputMs = (double) d.toNanosPart() / 1_000_000; |
|
627 return String.format("%.6f ms", outputMs); |
|
628 } else if (d.compareTo(SECOND) < 0) { |
|
629 // 0.001 ms - 999 ms |
|
630 int valueLength = countLength(d.toNanosPart()); |
|
631 int outputDigit = NANO_SIGNIFICANT_FIGURES - valueLength; |
|
632 double outputMs = (double) d.toNanosPart() / 1_000_000; |
|
633 return String.format("%." + outputDigit + "f ms", outputMs); |
|
634 } else if (d.compareTo(MINUTE) < 0) { |
|
635 // 1.00 s - 59.9 s |
|
636 int valueLength = countLength(d.toSecondsPart()); |
|
637 int outputDigit = MILL_SIGNIFICANT_FIGURES - valueLength; |
|
638 double outputSecond = d.toSecondsPart() + (double) d.toMillisPart() / 1_000; |
|
639 return String.format("%." + outputDigit + "f s", outputSecond); |
|
640 } else if (d.compareTo(HOUR) < 0) { |
|
641 // 1 m 0 s - 59 m 59 s |
|
642 return String.format("%d m %d s", d.toMinutesPart(), d.toSecondsPart()); |
|
643 } else if (d.compareTo(DAY) < 0) { |
|
644 // 1 h 0 m - 23 h 59 m |
|
645 return String.format("%d h %d m", d.toHoursPart(), d.toMinutesPart()); |
|
646 } else { |
|
647 // 1 d 0 h - |
|
648 return String.format("%d d %d h", d.toDaysPart(), d.toHoursPart()); |
|
649 } |
|
650 } |
|
651 |
|
652 private static int countLength(long value){ |
|
653 return (int) Math.log10(value) + 1; |
|
654 } |
|
655 |
|
656 private static Duration roundDuration(Duration d) { |
|
657 if (d.equals(Duration.ZERO)) { |
|
658 return d; |
|
659 } else if(d.isNegative()){ |
|
660 Duration roundedPositiveDuration = roundPositiveDuration(d.abs()); |
|
661 return roundedPositiveDuration.negated(); |
|
662 } else { |
|
663 return roundPositiveDuration(d); |
|
664 } |
|
665 } |
|
666 |
|
667 private static Duration roundPositiveDuration(Duration d){ |
|
668 if (d.compareTo(MICRO_SECOND) < 0) { |
|
669 // No round |
|
670 return d; |
|
671 } else if (d.compareTo(SECOND) < 0) { |
|
672 // Round significant figures to three digits |
|
673 int valueLength = countLength(d.toNanosPart()); |
|
674 int roundValue = (int) Math.pow(BASE, valueLength - DISPLAY_NANO_DIGIT); |
|
675 long roundedNanos = Math.round((double) d.toNanosPart() / roundValue) * roundValue; |
|
676 return d.truncatedTo(ChronoUnit.SECONDS).plusNanos(roundedNanos); |
|
677 } else if (d.compareTo(MINUTE) < 0) { |
|
678 // Round significant figures to three digits |
|
679 int valueLength = countLength(d.toSecondsPart()); |
|
680 int roundValue = (int) Math.pow(BASE, valueLength); |
|
681 long roundedMills = Math.round((double) d.toMillisPart() / roundValue) * roundValue; |
|
682 return d.truncatedTo(ChronoUnit.SECONDS).plusMillis(roundedMills); |
|
683 } else if (d.compareTo(HOUR) < 0) { |
|
684 // Round for more than 500 ms or less |
|
685 return d.plusMillis(SECOND.dividedBy(2).toMillisPart()).truncatedTo(ChronoUnit.SECONDS); |
|
686 } else if (d.compareTo(DAY) < 0) { |
|
687 // Round for more than 30 seconds or less |
|
688 return d.plusSeconds(MINUTE.dividedBy(2).toSecondsPart()).truncatedTo(ChronoUnit.MINUTES); |
|
689 } else { |
|
690 // Round for more than 30 minutes or less |
|
691 return d.plusMinutes(HOUR.dividedBy(2).toMinutesPart()).truncatedTo(ChronoUnit.HOURS); |
|
692 } |
|
693 } |
|
694 |
|
695 |
600 public static void takeNap(long millis) { |
696 public static void takeNap(long millis) { |
601 try { |
697 try { |
602 Thread.sleep(millis); |
698 Thread.sleep(millis); |
603 } catch (InterruptedException e) { |
699 } catch (InterruptedException e) { |
604 // ok |
700 // ok |