1 | /* |
2 | * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. |
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. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #ifndef SHARE_UTILITIES_EVENTS_HPP |
26 | #define SHARE_UTILITIES_EVENTS_HPP |
27 | |
28 | #include "memory/allocation.hpp" |
29 | #include "runtime/mutexLocker.hpp" |
30 | #include "runtime/thread.hpp" |
31 | #include "utilities/formatBuffer.hpp" |
32 | #include "utilities/globalDefinitions.hpp" |
33 | #include "utilities/ostream.hpp" |
34 | #include "utilities/vmError.hpp" |
35 | |
36 | // Events and EventMark provide interfaces to log events taking place in the vm. |
37 | // This facility is extremly useful for post-mortem debugging. The eventlog |
38 | // often provides crucial information about events leading up to the crash. |
39 | // |
40 | // Abstractly the logs can record whatever they way but normally they |
41 | // would record at least a timestamp and the current Thread, along |
42 | // with whatever data they need in a ring buffer. Commonly fixed |
43 | // length text messages are recorded for simplicity but other |
44 | // strategies could be used. Several logs are provided by default but |
45 | // new instances can be created as needed. |
46 | |
47 | // The base event log dumping class that is registered for dumping at |
48 | // crash time. This is a very generic interface that is mainly here |
49 | // for completeness. Normally the templated EventLogBase would be |
50 | // subclassed to provide different log types. |
51 | class EventLog : public CHeapObj<mtInternal> { |
52 | friend class Events; |
53 | |
54 | private: |
55 | EventLog* _next; |
56 | |
57 | EventLog* next() const { return _next; } |
58 | |
59 | public: |
60 | // Automatically registers the log so that it will be printed during |
61 | // crashes. |
62 | EventLog(); |
63 | |
64 | // Print log to output stream. |
65 | virtual void print_log_on(outputStream* out, int max = -1) = 0; |
66 | |
67 | // Returns true if s matches either the log name or the log handle. |
68 | virtual bool matches_name_or_handle(const char* s) const = 0; |
69 | |
70 | // Print log names (for help output of VM.events). |
71 | virtual void print_names(outputStream* out) const = 0; |
72 | |
73 | }; |
74 | |
75 | |
76 | // A templated subclass of EventLog that provides basic ring buffer |
77 | // functionality. Most event loggers should subclass this, possibly |
78 | // providing a more featureful log function if the existing copy |
79 | // semantics aren't appropriate. The name is used as the label of the |
80 | // log when it is dumped during a crash. |
81 | template <class T> class EventLogBase : public EventLog { |
82 | template <class X> class EventRecord : public CHeapObj<mtInternal> { |
83 | public: |
84 | double timestamp; |
85 | Thread* thread; |
86 | X data; |
87 | }; |
88 | |
89 | protected: |
90 | Mutex _mutex; |
91 | // Name is printed out as a header. |
92 | const char* _name; |
93 | // Handle is a short specifier used to select this particular event log |
94 | // for printing (see VM.events command). |
95 | const char* _handle; |
96 | int _length; |
97 | int _index; |
98 | int _count; |
99 | EventRecord<T>* _records; |
100 | |
101 | public: |
102 | EventLogBase<T>(const char* name, const char* handle, int length = LogEventsBufferEntries): |
103 | _mutex(Mutex::event, name, false, Monitor::_safepoint_check_never), |
104 | _name(name), |
105 | _handle(handle), |
106 | _length(length), |
107 | _index(0), |
108 | _count(0) { |
109 | _records = new EventRecord<T>[length]; |
110 | } |
111 | |
112 | double fetch_timestamp() { |
113 | return os::elapsedTime(); |
114 | } |
115 | |
116 | // move the ring buffer to next open slot and return the index of |
117 | // the slot to use for the current message. Should only be called |
118 | // while mutex is held. |
119 | int compute_log_index() { |
120 | int index = _index; |
121 | if (_count < _length) _count++; |
122 | _index++; |
123 | if (_index >= _length) _index = 0; |
124 | return index; |
125 | } |
126 | |
127 | bool should_log() { |
128 | // Don't bother adding new entries when we're crashing. This also |
129 | // avoids mutating the ring buffer when printing the log. |
130 | return !VMError::fatal_error_in_progress(); |
131 | } |
132 | |
133 | // Print the contents of the log |
134 | void print_log_on(outputStream* out, int max = -1); |
135 | |
136 | // Returns true if s matches either the log name or the log handle. |
137 | bool matches_name_or_handle(const char* s) const; |
138 | |
139 | // Print log names (for help output of VM.events). |
140 | void print_names(outputStream* out) const; |
141 | |
142 | private: |
143 | void print_log_impl(outputStream* out, int max = -1); |
144 | |
145 | // Print a single element. A templated implementation might need to |
146 | // be declared by subclasses. |
147 | void print(outputStream* out, T& e); |
148 | |
149 | void print(outputStream* out, EventRecord<T>& e) { |
150 | out->print("Event: %.3f " , e.timestamp); |
151 | if (e.thread != NULL) { |
152 | out->print("Thread " INTPTR_FORMAT " " , p2i(e.thread)); |
153 | } |
154 | print(out, e.data); |
155 | } |
156 | }; |
157 | |
158 | // A simple wrapper class for fixed size text messages. |
159 | template <size_t bufsz> |
160 | class FormatStringLogMessage : public FormatBuffer<bufsz> { |
161 | }; |
162 | typedef FormatStringLogMessage<256> StringLogMessage; |
163 | typedef FormatStringLogMessage<512> ExtendedStringLogMessage; |
164 | |
165 | // A simple ring buffer of fixed size text messages. |
166 | template <size_t bufsz> |
167 | class FormatStringEventLog : public EventLogBase< FormatStringLogMessage<bufsz> > { |
168 | public: |
169 | FormatStringEventLog(const char* name, const char* short_name, int count = LogEventsBufferEntries) |
170 | : EventLogBase< FormatStringLogMessage<bufsz> >(name, short_name, count) {} |
171 | |
172 | void logv(Thread* thread, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0) { |
173 | if (!this->should_log()) return; |
174 | |
175 | double timestamp = this->fetch_timestamp(); |
176 | MutexLocker ml(&this->_mutex, Mutex::_no_safepoint_check_flag); |
177 | int index = this->compute_log_index(); |
178 | this->_records[index].thread = thread; |
179 | this->_records[index].timestamp = timestamp; |
180 | this->_records[index].data.printv(format, ap); |
181 | } |
182 | |
183 | void log(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(3, 4) { |
184 | va_list ap; |
185 | va_start(ap, format); |
186 | this->logv(thread, format, ap); |
187 | va_end(ap); |
188 | } |
189 | }; |
190 | typedef FormatStringEventLog<256> StringEventLog; |
191 | typedef FormatStringEventLog<512> ExtendedStringEventLog; |
192 | |
193 | class InstanceKlass; |
194 | |
195 | // Event log for class unloading events to materialize the class name in place in the log stream. |
196 | class UnloadingEventLog : public EventLogBase<StringLogMessage> { |
197 | public: |
198 | UnloadingEventLog(const char* name, const char* short_name, int count = LogEventsBufferEntries) |
199 | : EventLogBase<StringLogMessage>(name, short_name, count) {} |
200 | |
201 | void log(Thread* thread, InstanceKlass* ik); |
202 | }; |
203 | |
204 | // Event log for exceptions |
205 | class ExceptionsEventLog : public ExtendedStringEventLog { |
206 | public: |
207 | ExceptionsEventLog(const char* name, const char* short_name, int count = LogEventsBufferEntries) |
208 | : ExtendedStringEventLog(name, short_name, count) {} |
209 | |
210 | void log(Thread* thread, Handle h_exception, const char* message, const char* file, int line); |
211 | }; |
212 | |
213 | |
214 | class Events : AllStatic { |
215 | friend class EventLog; |
216 | |
217 | private: |
218 | static EventLog* _logs; |
219 | |
220 | // A log for generic messages that aren't well categorized. |
221 | static StringEventLog* _messages; |
222 | |
223 | // A log for internal exception related messages, like internal |
224 | // throws and implicit exceptions. |
225 | static ExceptionsEventLog* _exceptions; |
226 | |
227 | // Deoptization related messages |
228 | static StringEventLog* _deopt_messages; |
229 | |
230 | // Redefinition related messages |
231 | static StringEventLog* _redefinitions; |
232 | |
233 | // Class unloading events |
234 | static UnloadingEventLog* _class_unloading; |
235 | public: |
236 | |
237 | // Print all event logs; limit number of events per event log to be printed with max |
238 | // (max == -1 prints all events). |
239 | static void print_all(outputStream* out, int max = -1); |
240 | |
241 | // Print a single event log specified by name or handle. |
242 | static void print_one(outputStream* out, const char* log_name, int max = -1); |
243 | |
244 | // Dump all events to the tty |
245 | static void print(); |
246 | |
247 | // Logs a generic message with timestamp and format as printf. |
248 | static void log(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3); |
249 | |
250 | // Log exception related message |
251 | static void log_exception(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3); |
252 | static void log_exception(Thread* thread, Handle h_exception, const char* message, const char* file, int line); |
253 | |
254 | static void log_redefinition(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3); |
255 | |
256 | static void log_class_unloading(Thread* thread, InstanceKlass* ik); |
257 | |
258 | static void log_deopt_message(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3); |
259 | |
260 | // Register default loggers |
261 | static void init(); |
262 | }; |
263 | |
264 | inline void Events::log(Thread* thread, const char* format, ...) { |
265 | if (LogEvents && _messages != NULL) { |
266 | va_list ap; |
267 | va_start(ap, format); |
268 | _messages->logv(thread, format, ap); |
269 | va_end(ap); |
270 | } |
271 | } |
272 | |
273 | inline void Events::log_exception(Thread* thread, const char* format, ...) { |
274 | if (LogEvents && _exceptions != NULL) { |
275 | va_list ap; |
276 | va_start(ap, format); |
277 | _exceptions->logv(thread, format, ap); |
278 | va_end(ap); |
279 | } |
280 | } |
281 | |
282 | inline void Events::log_exception(Thread* thread, Handle h_exception, const char* message, const char* file, int line) { |
283 | if (LogEvents && _exceptions != NULL) { |
284 | _exceptions->log(thread, h_exception, message, file, line); |
285 | } |
286 | } |
287 | |
288 | inline void Events::log_redefinition(Thread* thread, const char* format, ...) { |
289 | if (LogEvents && _redefinitions != NULL) { |
290 | va_list ap; |
291 | va_start(ap, format); |
292 | _redefinitions->logv(thread, format, ap); |
293 | va_end(ap); |
294 | } |
295 | } |
296 | |
297 | inline void Events::log_class_unloading(Thread* thread, InstanceKlass* ik) { |
298 | if (LogEvents && _class_unloading != NULL) { |
299 | _class_unloading->log(thread, ik); |
300 | } |
301 | } |
302 | |
303 | inline void Events::log_deopt_message(Thread* thread, const char* format, ...) { |
304 | if (LogEvents && _deopt_messages != NULL) { |
305 | va_list ap; |
306 | va_start(ap, format); |
307 | _deopt_messages->logv(thread, format, ap); |
308 | va_end(ap); |
309 | } |
310 | } |
311 | |
312 | template <class T> |
313 | inline void EventLogBase<T>::print_log_on(outputStream* out, int max) { |
314 | if (Thread::current_or_null() == NULL) { |
315 | // Not yet attached? Don't try to use locking |
316 | print_log_impl(out, max); |
317 | } else { |
318 | MutexLocker ml(&_mutex, Mutex::_no_safepoint_check_flag); |
319 | print_log_impl(out, max); |
320 | } |
321 | } |
322 | |
323 | template <class T> |
324 | inline bool EventLogBase<T>::matches_name_or_handle(const char* s) const { |
325 | return ::strcasecmp(s, _name) == 0 || |
326 | ::strcasecmp(s, _handle) == 0; |
327 | } |
328 | |
329 | template <class T> |
330 | inline void EventLogBase<T>::print_names(outputStream* out) const { |
331 | out->print("\"%s\" : %s" , _handle, _name); |
332 | } |
333 | |
334 | // Dump the ring buffer entries that current have entries. |
335 | template <class T> |
336 | inline void EventLogBase<T>::print_log_impl(outputStream* out, int max) { |
337 | out->print_cr("%s (%d events):" , _name, _count); |
338 | if (_count == 0) { |
339 | out->print_cr("No events" ); |
340 | out->cr(); |
341 | return; |
342 | } |
343 | |
344 | int printed = 0; |
345 | if (_count < _length) { |
346 | for (int i = 0; i < _count; i++) { |
347 | if (max > 0 && printed == max) { |
348 | break; |
349 | } |
350 | print(out, _records[i]); |
351 | printed ++; |
352 | } |
353 | } else { |
354 | for (int i = _index; i < _length; i++) { |
355 | if (max > 0 && printed == max) { |
356 | break; |
357 | } |
358 | print(out, _records[i]); |
359 | printed ++; |
360 | } |
361 | for (int i = 0; i < _index; i++) { |
362 | if (max > 0 && printed == max) { |
363 | break; |
364 | } |
365 | print(out, _records[i]); |
366 | printed ++; |
367 | } |
368 | } |
369 | |
370 | if (printed == max) { |
371 | out->print_cr("...(skipped)" ); |
372 | } |
373 | |
374 | out->cr(); |
375 | } |
376 | |
377 | // Implement a printing routine for the StringLogMessage |
378 | template <> |
379 | inline void EventLogBase<StringLogMessage>::print(outputStream* out, StringLogMessage& lm) { |
380 | out->print_raw(lm); |
381 | out->cr(); |
382 | } |
383 | |
384 | // Implement a printing routine for the ExtendedStringLogMessage |
385 | template <> |
386 | inline void EventLogBase<ExtendedStringLogMessage>::print(outputStream* out, ExtendedStringLogMessage& lm) { |
387 | out->print_raw(lm); |
388 | out->cr(); |
389 | } |
390 | |
391 | // Place markers for the beginning and end up of a set of events. |
392 | // These end up in the default log. |
393 | class EventMark : public StackObj { |
394 | StringLogMessage _buffer; |
395 | |
396 | public: |
397 | // log a begin event, format as printf |
398 | EventMark(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); |
399 | // log an end event |
400 | ~EventMark(); |
401 | }; |
402 | |
403 | #endif // SHARE_UTILITIES_EVENTS_HPP |
404 | |