32 import java.util.Collection; |
32 import java.util.Collection; |
33 import java.util.List; |
33 import java.util.List; |
34 import java.util.Objects; |
34 import java.util.Objects; |
35 import java.util.concurrent.CopyOnWriteArrayList; |
35 import java.util.concurrent.CopyOnWriteArrayList; |
36 import java.util.function.Predicate; |
36 import java.util.function.Predicate; |
|
37 import jdk.jfr.Event; |
|
38 import jdk.jfr.EventType; |
37 |
39 |
38 public final class RequestEngine { |
40 public final class RequestEngine { |
39 |
41 |
40 private final static JVM jvm = JVM.getJVM(); |
42 private final static JVM jvm = JVM.getJVM(); |
41 |
43 |
58 } |
60 } |
59 |
61 |
60 private void execute() { |
62 private void execute() { |
61 try { |
63 try { |
62 if (accessControllerContext == null) { // native |
64 if (accessControllerContext == null) { // native |
63 jvm.emitEvent(type.getId(), JVM.counterTime(), 0); |
65 if (type.isJDK()) { |
|
66 hook.run(); |
|
67 } else { |
|
68 jvm.emitEvent(type.getId(), JVM.counterTime(), 0); |
|
69 } |
64 Logger.log(LogTag.JFR_SYSTEM_EVENT, LogLevel.DEBUG, ()-> "Executed periodic hook for " + type.getLogName()); |
70 Logger.log(LogTag.JFR_SYSTEM_EVENT, LogLevel.DEBUG, ()-> "Executed periodic hook for " + type.getLogName()); |
65 } else { |
71 } else { |
66 executeSecure(); |
72 executeSecure(); |
67 } |
73 } |
68 } catch (Throwable e) { |
74 } catch (Throwable e) { |
89 } |
95 } |
90 |
96 |
91 private final static List<RequestHook> entries = new CopyOnWriteArrayList<>(); |
97 private final static List<RequestHook> entries = new CopyOnWriteArrayList<>(); |
92 private static long lastTimeMillis; |
98 private static long lastTimeMillis; |
93 |
99 |
94 // Insertion takes O(2*n), could be O(1) with HashMap, but |
|
95 // thinking is that CopyOnWriteArrayList is faster |
|
96 // to iterate over, which will happen more over time. |
|
97 public static void addHook(AccessControlContext acc, PlatformEventType type, Runnable hook) { |
100 public static void addHook(AccessControlContext acc, PlatformEventType type, Runnable hook) { |
98 Objects.requireNonNull(acc); |
101 Objects.requireNonNull(acc); |
|
102 addHookInternal(acc, type, hook); |
|
103 } |
|
104 |
|
105 private static void addHookInternal(AccessControlContext acc, PlatformEventType type, Runnable hook) { |
99 RequestHook he = new RequestHook(acc, type, hook); |
106 RequestHook he = new RequestHook(acc, type, hook); |
100 for (RequestHook e : entries) { |
107 for (RequestHook e : entries) { |
101 if (e.hook == hook) { |
108 if (e.hook == hook) { |
102 throw new IllegalArgumentException("Hook has already been added"); |
109 throw new IllegalArgumentException("Hook has already been added"); |
103 } |
110 } |
104 } |
111 } |
105 he.type.setEventHook(true); |
112 he.type.setEventHook(true); |
|
113 // Insertion takes O(2*n), could be O(1) with HashMap, but |
|
114 // thinking is that CopyOnWriteArrayList is faster |
|
115 // to iterate over, which will happen more over time. |
106 entries.add(he); |
116 entries.add(he); |
107 logHook("Added", type); |
117 logHook("Added", type); |
108 } |
118 } |
109 |
119 |
|
120 public static void addTrustedJDKHook(Class<? extends Event> eventClass, Runnable runnable) { |
|
121 if (eventClass.getClassLoader() != null) { |
|
122 throw new SecurityException("Hook can only be registered for event classes that are loaded by the bootstrap class loader"); |
|
123 } |
|
124 if (runnable.getClass().getClassLoader() != null) { |
|
125 throw new SecurityException("Runnable hook class must be loaded by the bootstrap class loader"); |
|
126 } |
|
127 EventType eType = MetadataRepository.getInstance().getEventType(eventClass); |
|
128 PlatformEventType pType = PrivateAccess.getInstance().getPlatformEventType(eType); |
|
129 addHookInternal(null, pType, runnable); |
|
130 } |
110 |
131 |
111 private static void logHook(String action, PlatformEventType type) { |
132 private static void logHook(String action, PlatformEventType type) { |
112 if (type.isJDK() || type.isJVM()) { |
133 if (type.isJDK() || type.isJVM()) { |
113 Logger.log(LogTag.JFR_SYSTEM_EVENT, LogLevel.INFO, action + " periodic hook for " + type.getLogName()); |
134 Logger.log(LogTag.JFR_SYSTEM_EVENT, LogLevel.INFO, action + " periodic hook for " + type.getLogName()); |
114 } else { |
135 } else { |