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.
51class 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.
81template <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.
159template <size_t bufsz>
160class FormatStringLogMessage : public FormatBuffer<bufsz> {
161};
162typedef FormatStringLogMessage<256> StringLogMessage;
163typedef FormatStringLogMessage<512> ExtendedStringLogMessage;
164
165// A simple ring buffer of fixed size text messages.
166template <size_t bufsz>
167class 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};
190typedef FormatStringEventLog<256> StringEventLog;
191typedef FormatStringEventLog<512> ExtendedStringEventLog;
192
193class InstanceKlass;
194
195// Event log for class unloading events to materialize the class name in place in the log stream.
196class 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
205class 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
214class 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
264inline 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
273inline 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
282inline 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
288inline 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
297inline void Events::log_class_unloading(Thread* thread, InstanceKlass* ik) {
298 if (LogEvents && _class_unloading != NULL) {
299 _class_unloading->log(thread, ik);
300 }
301}
302
303inline 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
312template <class T>
313inline 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
323template <class T>
324inline bool EventLogBase<T>::matches_name_or_handle(const char* s) const {
325 return ::strcasecmp(s, _name) == 0 ||
326 ::strcasecmp(s, _handle) == 0;
327}
328
329template <class T>
330inline 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.
335template <class T>
336inline 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
378template <>
379inline 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
385template <>
386inline 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.
393class 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