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.instrument;
27
28 import java.util.ArrayList;
29 import java.util.List;
30
31 import jdk.jfr.Event;
32 import jdk.jfr.events.ActiveRecordingEvent;
33 import jdk.jfr.events.ActiveSettingEvent;
34 import jdk.jfr.events.ErrorThrownEvent;
35 import jdk.jfr.events.ExceptionStatisticsEvent;
36 import jdk.jfr.events.ExceptionThrownEvent;
37 import jdk.jfr.events.FileForceEvent;
38 import jdk.jfr.events.FileReadEvent;
39 import jdk.jfr.events.FileWriteEvent;
40 import jdk.jfr.events.SecurityPropertyModificationEvent;
41 import jdk.jfr.events.SocketReadEvent;
42 import jdk.jfr.events.SocketWriteEvent;
43 import jdk.jfr.events.TLSHandshakeEvent;
44 import jdk.jfr.events.X509CertificateEvent;
45 import jdk.jfr.events.X509ValidationEvent;
46 import jdk.jfr.internal.JVM;
47 import jdk.jfr.internal.LogLevel;
48 import jdk.jfr.internal.LogTag;
49 import jdk.jfr.internal.Logger;
50 import jdk.jfr.internal.RequestEngine;
51 import jdk.jfr.internal.SecuritySupport;
52
53 public final class JDKEvents {
56 SecurityPropertyModificationEvent.class,
57 TLSHandshakeEvent.class,
58 X509CertificateEvent.class,
59 X509ValidationEvent.class
60 };
61
62 private static final Class<?>[] eventClasses = {
63 FileForceEvent.class,
64 FileReadEvent.class,
65 FileWriteEvent.class,
66 SocketReadEvent.class,
67 SocketWriteEvent.class,
68 ExceptionThrownEvent.class,
69 ExceptionStatisticsEvent.class,
70 ErrorThrownEvent.class,
71 ActiveSettingEvent.class,
72 ActiveRecordingEvent.class,
73 jdk.internal.event.SecurityPropertyModificationEvent.class,
74 jdk.internal.event.TLSHandshakeEvent.class,
75 jdk.internal.event.X509CertificateEvent.class,
76 jdk.internal.event.X509ValidationEvent.class
77 };
78
79 // This is a list of the classes with instrumentation code that should be applied.
80 private static final Class<?>[] instrumentationClasses = new Class<?>[] {
81 FileInputStreamInstrumentor.class,
82 FileOutputStreamInstrumentor.class,
83 RandomAccessFileInstrumentor.class,
84 FileChannelImplInstrumentor.class,
85 SocketInputStreamInstrumentor.class,
86 SocketOutputStreamInstrumentor.class,
87 SocketChannelImplInstrumentor.class
88 };
89
90 private static final Class<?>[] targetClasses = new Class<?>[instrumentationClasses.length];
91 private static final JVM jvm = JVM.getJVM();
92 private static final Runnable emitExceptionStatistics = JDKEvents::emitExceptionStatistics;
93 private static boolean initializationTriggered;
94
95 @SuppressWarnings("unchecked")
96 public synchronized static void initialize() {
97 try {
98 if (initializationTriggered == false) {
99 for (Class<?> mirrorEventClass : mirrorEventClasses) {
100 SecuritySupport.registerMirror(((Class<? extends Event>)mirrorEventClass));
101 }
102 for (Class<?> eventClass : eventClasses) {
103 SecuritySupport.registerEvent((Class<? extends Event>) eventClass);
104 }
105 initializationTriggered = true;
106 RequestEngine.addTrustedJDKHook(ExceptionStatisticsEvent.class, emitExceptionStatistics);
107 }
108 } catch (Exception e) {
109 Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not initialize JDK events. " + e.getMessage());
110 }
111 }
112
113 public static void addInstrumentation() {
114 try {
115 List<Class<?>> list = new ArrayList<>();
116 for (int i = 0; i < instrumentationClasses.length; i++) {
117 JIInstrumentationTarget tgt = instrumentationClasses[i].getAnnotation(JIInstrumentationTarget.class);
118 Class<?> clazz = Class.forName(tgt.value());
119 targetClasses[i] = clazz;
120 list.add(clazz);
121 }
122 list.add(java.lang.Throwable.class);
123 list.add(java.lang.Error.class);
124 Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Retransformed JDK classes");
125 jvm.retransformClasses(list.toArray(new Class<?>[list.size()]));
126 } catch (IllegalStateException ise) {
143 return ConstructorTracerWriter.generateBytes(java.lang.Throwable.class, oldBytes);
144 }
145
146 if (java.lang.Error.class == klass) {
147 Logger.log(LogTag.JFR_SYSTEM, LogLevel.TRACE, "Instrumenting java.lang.Error");
148 return ConstructorTracerWriter.generateBytes(java.lang.Error.class, oldBytes);
149 }
150
151 for (int i = 0; i < targetClasses.length; i++) {
152 if (targetClasses[i].equals(klass)) {
153 Class<?> c = instrumentationClasses[i];
154 Logger.log(LogTag.JFR_SYSTEM, LogLevel.TRACE, () -> "Processing instrumentation class: " + c);
155 return new JIClassInstrumentation(instrumentationClasses[i], klass, oldBytes).getNewBytes();
156 }
157 }
158 return oldBytes;
159 }
160
161 public static void remove() {
162 RequestEngine.removeHook(JDKEvents::emitExceptionStatistics);
163 }
164 }
|
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.instrument;
27
28 import java.util.ArrayList;
29 import java.util.List;
30
31 import jdk.internal.misc.VM;
32 import jdk.internal.misc.VM.BufferPool;
33
34 import jdk.jfr.Event;
35 import jdk.jfr.events.ActiveRecordingEvent;
36 import jdk.jfr.events.ActiveSettingEvent;
37 import jdk.jfr.events.DirectMemoryStatisticsEvent;
38 import jdk.jfr.events.ErrorThrownEvent;
39 import jdk.jfr.events.ExceptionStatisticsEvent;
40 import jdk.jfr.events.ExceptionThrownEvent;
41 import jdk.jfr.events.FileForceEvent;
42 import jdk.jfr.events.FileReadEvent;
43 import jdk.jfr.events.FileWriteEvent;
44 import jdk.jfr.events.SecurityPropertyModificationEvent;
45 import jdk.jfr.events.SocketReadEvent;
46 import jdk.jfr.events.SocketWriteEvent;
47 import jdk.jfr.events.TLSHandshakeEvent;
48 import jdk.jfr.events.X509CertificateEvent;
49 import jdk.jfr.events.X509ValidationEvent;
50 import jdk.jfr.internal.JVM;
51 import jdk.jfr.internal.LogLevel;
52 import jdk.jfr.internal.LogTag;
53 import jdk.jfr.internal.Logger;
54 import jdk.jfr.internal.RequestEngine;
55 import jdk.jfr.internal.SecuritySupport;
56
57 public final class JDKEvents {
60 SecurityPropertyModificationEvent.class,
61 TLSHandshakeEvent.class,
62 X509CertificateEvent.class,
63 X509ValidationEvent.class
64 };
65
66 private static final Class<?>[] eventClasses = {
67 FileForceEvent.class,
68 FileReadEvent.class,
69 FileWriteEvent.class,
70 SocketReadEvent.class,
71 SocketWriteEvent.class,
72 ExceptionThrownEvent.class,
73 ExceptionStatisticsEvent.class,
74 ErrorThrownEvent.class,
75 ActiveSettingEvent.class,
76 ActiveRecordingEvent.class,
77 jdk.internal.event.SecurityPropertyModificationEvent.class,
78 jdk.internal.event.TLSHandshakeEvent.class,
79 jdk.internal.event.X509CertificateEvent.class,
80 jdk.internal.event.X509ValidationEvent.class,
81 DirectMemoryStatisticsEvent.class
82 };
83
84 // This is a list of the classes with instrumentation code that should be applied.
85 private static final Class<?>[] instrumentationClasses = new Class<?>[] {
86 FileInputStreamInstrumentor.class,
87 FileOutputStreamInstrumentor.class,
88 RandomAccessFileInstrumentor.class,
89 FileChannelImplInstrumentor.class,
90 SocketInputStreamInstrumentor.class,
91 SocketOutputStreamInstrumentor.class,
92 SocketChannelImplInstrumentor.class
93 };
94
95 private static final Class<?>[] targetClasses = new Class<?>[instrumentationClasses.length];
96 private static final JVM jvm = JVM.getJVM();
97 private static final Runnable emitExceptionStatistics = JDKEvents::emitExceptionStatistics;
98 private static final Runnable emitDirectMemoryStatistics = JDKEvents::emitDirectMemoryStatistics;
99 private static boolean initializationTriggered;
100
101 @SuppressWarnings("unchecked")
102 public synchronized static void initialize() {
103 try {
104 if (initializationTriggered == false) {
105 for (Class<?> mirrorEventClass : mirrorEventClasses) {
106 SecuritySupport.registerMirror(((Class<? extends Event>)mirrorEventClass));
107 }
108 for (Class<?> eventClass : eventClasses) {
109 SecuritySupport.registerEvent((Class<? extends Event>) eventClass);
110 }
111 initializationTriggered = true;
112 RequestEngine.addTrustedJDKHook(ExceptionStatisticsEvent.class, emitExceptionStatistics);
113 RequestEngine.addTrustedJDKHook(DirectMemoryStatisticsEvent.class, emitDirectMemoryStatistics);
114 }
115 } catch (Exception e) {
116 Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not initialize JDK events. " + e.getMessage());
117 }
118 }
119
120 public static void addInstrumentation() {
121 try {
122 List<Class<?>> list = new ArrayList<>();
123 for (int i = 0; i < instrumentationClasses.length; i++) {
124 JIInstrumentationTarget tgt = instrumentationClasses[i].getAnnotation(JIInstrumentationTarget.class);
125 Class<?> clazz = Class.forName(tgt.value());
126 targetClasses[i] = clazz;
127 list.add(clazz);
128 }
129 list.add(java.lang.Throwable.class);
130 list.add(java.lang.Error.class);
131 Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Retransformed JDK classes");
132 jvm.retransformClasses(list.toArray(new Class<?>[list.size()]));
133 } catch (IllegalStateException ise) {
150 return ConstructorTracerWriter.generateBytes(java.lang.Throwable.class, oldBytes);
151 }
152
153 if (java.lang.Error.class == klass) {
154 Logger.log(LogTag.JFR_SYSTEM, LogLevel.TRACE, "Instrumenting java.lang.Error");
155 return ConstructorTracerWriter.generateBytes(java.lang.Error.class, oldBytes);
156 }
157
158 for (int i = 0; i < targetClasses.length; i++) {
159 if (targetClasses[i].equals(klass)) {
160 Class<?> c = instrumentationClasses[i];
161 Logger.log(LogTag.JFR_SYSTEM, LogLevel.TRACE, () -> "Processing instrumentation class: " + c);
162 return new JIClassInstrumentation(instrumentationClasses[i], klass, oldBytes).getNewBytes();
163 }
164 }
165 return oldBytes;
166 }
167
168 public static void remove() {
169 RequestEngine.removeHook(JDKEvents::emitExceptionStatistics);
170 RequestEngine.removeHook(emitDirectMemoryStatistics);
171 }
172
173 private static final BufferPool DIRECT_BUFFER_POOL = VM.getBufferPools().stream()
174 .filter(p -> "direct".equals(p.getName()))
175 .findFirst().get();
176
177 private static void emitDirectMemoryStatistics() {
178 DirectMemoryStatisticsEvent e = new DirectMemoryStatisticsEvent();
179 e.count = DIRECT_BUFFER_POOL.getCount();
180 e.totalCapacity = DIRECT_BUFFER_POOL.getTotalCapacity();
181 e.memoryUsed = DIRECT_BUFFER_POOL.getMemoryUsed();
182 e.maxCapacity = VM.maxDirectMemory();
183 e.commit();
184 }
185 }
|