Mercurial > hg > truffle
annotate src/share/vm/utilities/ostream.cpp @ 6862:8a5ea0a9ccc4
7127708: G1: change task num types from int to uint in concurrent mark
Summary: Change the type of various task num fields, parameters etc to unsigned and rename them to be more consistent with the other collectors. Code changes were also reviewed by Vitaly Davidovich.
Reviewed-by: johnc
Contributed-by: Kaushik Srenevasan <kaushik@twitter.com>
author | johnc |
---|---|
date | Sat, 06 Oct 2012 01:17:44 -0700 |
parents | 4ee06e614636 |
children | c38f13903fdf c3e799c37717 |
rev | line source |
---|---|
0 | 1 /* |
6605 | 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1353
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1353
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1353
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "compiler/compileLog.hpp" | |
27 #include "oops/oop.inline.hpp" | |
28 #include "runtime/arguments.hpp" | |
29 #include "utilities/defaultStream.hpp" | |
30 #include "utilities/ostream.hpp" | |
31 #include "utilities/top.hpp" | |
32 #include "utilities/xmlstream.hpp" | |
33 #ifdef TARGET_OS_FAMILY_linux | |
34 # include "os_linux.inline.hpp" | |
35 #endif | |
36 #ifdef TARGET_OS_FAMILY_solaris | |
37 # include "os_solaris.inline.hpp" | |
38 #endif | |
39 #ifdef TARGET_OS_FAMILY_windows | |
40 # include "os_windows.inline.hpp" | |
41 #endif | |
3960 | 42 #ifdef TARGET_OS_FAMILY_bsd |
43 # include "os_bsd.inline.hpp" | |
44 #endif | |
0 | 45 |
46 extern "C" void jio_print(const char* s); // Declarationtion of jvm method | |
47 | |
48 outputStream::outputStream(int width) { | |
49 _width = width; | |
50 _position = 0; | |
51 _newlines = 0; | |
52 _precount = 0; | |
53 _indentation = 0; | |
54 } | |
55 | |
56 outputStream::outputStream(int width, bool has_time_stamps) { | |
57 _width = width; | |
58 _position = 0; | |
59 _newlines = 0; | |
60 _precount = 0; | |
61 _indentation = 0; | |
62 if (has_time_stamps) _stamp.update(); | |
63 } | |
64 | |
65 void outputStream::update_position(const char* s, size_t len) { | |
66 for (size_t i = 0; i < len; i++) { | |
67 char ch = s[i]; | |
68 if (ch == '\n') { | |
69 _newlines += 1; | |
70 _precount += _position + 1; | |
71 _position = 0; | |
72 } else if (ch == '\t') { | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
73 int tw = 8 - (_position & 7); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
74 _position += tw; |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
75 _precount -= tw-1; // invariant: _precount + _position == total count |
0 | 76 } else { |
77 _position += 1; | |
78 } | |
79 } | |
80 } | |
81 | |
82 // Execute a vsprintf, using the given buffer if necessary. | |
83 // Return a pointer to the formatted string. | |
84 const char* outputStream::do_vsnprintf(char* buffer, size_t buflen, | |
85 const char* format, va_list ap, | |
86 bool add_cr, | |
87 size_t& result_len) { | |
88 const char* result; | |
89 if (add_cr) buflen--; | |
90 if (!strchr(format, '%')) { | |
91 // constant format string | |
92 result = format; | |
93 result_len = strlen(result); | |
94 if (add_cr && result_len >= buflen) result_len = buflen-1; // truncate | |
95 } else if (format[0] == '%' && format[1] == 's' && format[2] == '\0') { | |
96 // trivial copy-through format string | |
97 result = va_arg(ap, const char*); | |
98 result_len = strlen(result); | |
99 if (add_cr && result_len >= buflen) result_len = buflen-1; // truncate | |
100 } else if (vsnprintf(buffer, buflen, format, ap) >= 0) { | |
101 result = buffer; | |
102 result_len = strlen(result); | |
103 } else { | |
104 DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");) | |
105 result = buffer; | |
106 result_len = buflen - 1; | |
107 buffer[result_len] = 0; | |
108 } | |
109 if (add_cr) { | |
110 if (result != buffer) { | |
111 strncpy(buffer, result, buflen); | |
112 result = buffer; | |
113 } | |
114 buffer[result_len++] = '\n'; | |
115 buffer[result_len] = 0; | |
116 } | |
117 return result; | |
118 } | |
119 | |
120 void outputStream::print(const char* format, ...) { | |
121 char buffer[O_BUFLEN]; | |
122 va_list ap; | |
123 va_start(ap, format); | |
124 size_t len; | |
125 const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, false, len); | |
126 write(str, len); | |
127 va_end(ap); | |
128 } | |
129 | |
130 void outputStream::print_cr(const char* format, ...) { | |
131 char buffer[O_BUFLEN]; | |
132 va_list ap; | |
133 va_start(ap, format); | |
134 size_t len; | |
135 const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, true, len); | |
136 write(str, len); | |
137 va_end(ap); | |
138 } | |
139 | |
140 void outputStream::vprint(const char *format, va_list argptr) { | |
141 char buffer[O_BUFLEN]; | |
142 size_t len; | |
143 const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, false, len); | |
144 write(str, len); | |
145 } | |
146 | |
147 void outputStream::vprint_cr(const char* format, va_list argptr) { | |
148 char buffer[O_BUFLEN]; | |
149 size_t len; | |
150 const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, true, len); | |
151 write(str, len); | |
152 } | |
153 | |
154 void outputStream::fill_to(int col) { | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
155 int need_fill = col - position(); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
156 sp(need_fill); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
157 } |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
158 |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
159 void outputStream::move_to(int col, int slop, int min_space) { |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
160 if (position() >= col + slop) |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
161 cr(); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
162 int need_fill = col - position(); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
163 if (need_fill < min_space) |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
164 need_fill = min_space; |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
165 sp(need_fill); |
0 | 166 } |
167 | |
168 void outputStream::put(char ch) { | |
169 assert(ch != 0, "please fix call site"); | |
170 char buf[] = { ch, '\0' }; | |
171 write(buf, 1); | |
172 } | |
173 | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
174 #define SP_USE_TABS false |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
175 |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
176 void outputStream::sp(int count) { |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
177 if (count < 0) return; |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
178 if (SP_USE_TABS && count >= 8) { |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
179 int target = position() + count; |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
180 while (count >= 8) { |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
181 this->write("\t", 1); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
182 count -= 8; |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
183 } |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
184 count = target - position(); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
185 } |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
186 while (count > 0) { |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
187 int nw = (count > 8) ? 8 : count; |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
188 this->write(" ", nw); |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
189 count -= nw; |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
190 } |
0 | 191 } |
192 | |
193 void outputStream::cr() { | |
194 this->write("\n", 1); | |
195 } | |
196 | |
197 void outputStream::stamp() { | |
198 if (! _stamp.is_updated()) { | |
199 _stamp.update(); // start at 0 on first call to stamp() | |
200 } | |
201 | |
202 // outputStream::stamp() may get called by ostream_abort(), use snprintf | |
203 // to avoid allocating large stack buffer in print(). | |
204 char buf[40]; | |
205 jio_snprintf(buf, sizeof(buf), "%.3f", _stamp.seconds()); | |
206 print_raw(buf); | |
207 } | |
208 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
209 void outputStream::stamp(bool guard, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
210 const char* prefix, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
211 const char* suffix) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
212 if (!guard) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
213 return; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
214 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
215 print_raw(prefix); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
216 stamp(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
217 print_raw(suffix); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
218 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
102
diff
changeset
|
219 |
0 | 220 void outputStream::date_stamp(bool guard, |
221 const char* prefix, | |
222 const char* suffix) { | |
223 if (!guard) { | |
224 return; | |
225 } | |
226 print_raw(prefix); | |
227 static const char error_time[] = "yyyy-mm-ddThh:mm:ss.mmm+zzzz"; | |
228 static const int buffer_length = 32; | |
229 char buffer[buffer_length]; | |
230 const char* iso8601_result = os::iso8601_time(buffer, buffer_length); | |
231 if (iso8601_result != NULL) { | |
232 print_raw(buffer); | |
233 } else { | |
234 print_raw(error_time); | |
235 } | |
236 print_raw(suffix); | |
237 return; | |
238 } | |
239 | |
6605 | 240 outputStream& outputStream::indent() { |
0 | 241 while (_position < _indentation) sp(); |
6605 | 242 return *this; |
0 | 243 } |
244 | |
245 void outputStream::print_jlong(jlong value) { | |
246 // N.B. Same as INT64_FORMAT | |
247 print(os::jlong_format_specifier(), value); | |
248 } | |
249 | |
250 void outputStream::print_julong(julong value) { | |
251 // N.B. Same as UINT64_FORMAT | |
252 print(os::julong_format_specifier(), value); | |
253 } | |
254 | |
6605 | 255 /** |
256 * This prints out hex data in a 'windbg' or 'xxd' form, where each line is: | |
257 * <hex-address>: 8 * <hex-halfword> <ascii translation (optional)> | |
258 * example: | |
259 * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000 .DOF............ | |
260 * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005 .......@... .... | |
261 * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......] | |
262 * ... | |
263 * | |
264 * indent is applied to each line. Ends with a CR. | |
265 */ | |
266 void outputStream::print_data(void* data, size_t len, bool with_ascii) { | |
267 size_t limit = (len + 16) / 16 * 16; | |
268 for (size_t i = 0; i < limit; ++i) { | |
269 if (i % 16 == 0) { | |
270 indent().print("%07x:", i); | |
271 } | |
272 if (i % 2 == 0) { | |
273 print(" "); | |
274 } | |
275 if (i < len) { | |
276 print("%02x", ((unsigned char*)data)[i]); | |
277 } else { | |
278 print(" "); | |
279 } | |
280 if ((i + 1) % 16 == 0) { | |
281 if (with_ascii) { | |
282 print(" "); | |
283 for (size_t j = 0; j < 16; ++j) { | |
284 size_t idx = i + j - 15; | |
285 if (idx < len) { | |
286 char c = ((char*)data)[idx]; | |
287 print("%c", c >= 32 && c <= 126 ? c : '.'); | |
288 } | |
289 } | |
290 } | |
291 print_cr(""); | |
292 } | |
293 } | |
294 } | |
295 | |
0 | 296 stringStream::stringStream(size_t initial_size) : outputStream() { |
297 buffer_length = initial_size; | |
298 buffer = NEW_RESOURCE_ARRAY(char, buffer_length); | |
299 buffer_pos = 0; | |
300 buffer_fixed = false; | |
301 } | |
302 | |
303 // useful for output to fixed chunks of memory, such as performance counters | |
304 stringStream::stringStream(char* fixed_buffer, size_t fixed_buffer_size) : outputStream() { | |
305 buffer_length = fixed_buffer_size; | |
306 buffer = fixed_buffer; | |
307 buffer_pos = 0; | |
308 buffer_fixed = true; | |
309 } | |
310 | |
311 void stringStream::write(const char* s, size_t len) { | |
312 size_t write_len = len; // number of non-null bytes to write | |
313 size_t end = buffer_pos + len + 1; // position after write and final '\0' | |
314 if (end > buffer_length) { | |
315 if (buffer_fixed) { | |
316 // if buffer cannot resize, silently truncate | |
317 end = buffer_length; | |
318 write_len = end - buffer_pos - 1; // leave room for the final '\0' | |
319 } else { | |
320 // For small overruns, double the buffer. For larger ones, | |
321 // increase to the requested size. | |
322 if (end < buffer_length * 2) { | |
323 end = buffer_length * 2; | |
324 } | |
325 char* oldbuf = buffer; | |
326 buffer = NEW_RESOURCE_ARRAY(char, end); | |
327 strncpy(buffer, oldbuf, buffer_pos); | |
328 buffer_length = end; | |
329 } | |
330 } | |
331 // invariant: buffer is always null-terminated | |
332 guarantee(buffer_pos + write_len + 1 <= buffer_length, "stringStream oob"); | |
333 buffer[buffer_pos + write_len] = 0; | |
334 strncpy(buffer + buffer_pos, s, write_len); | |
335 buffer_pos += write_len; | |
336 | |
337 // Note that the following does not depend on write_len. | |
338 // This means that position and count get updated | |
339 // even when overflow occurs. | |
340 update_position(s, len); | |
341 } | |
342 | |
343 char* stringStream::as_string() { | |
344 char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1); | |
345 strncpy(copy, buffer, buffer_pos); | |
346 copy[buffer_pos] = 0; // terminating null | |
347 return copy; | |
348 } | |
349 | |
350 stringStream::~stringStream() {} | |
351 | |
352 xmlStream* xtty; | |
353 outputStream* tty; | |
354 outputStream* gclog_or_tty; | |
355 extern Mutex* tty_lock; | |
356 | |
357 fileStream::fileStream(const char* file_name) { | |
358 _file = fopen(file_name, "w"); | |
359 _need_close = true; | |
360 } | |
361 | |
2199
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
362 fileStream::fileStream(const char* file_name, const char* opentype) { |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
363 _file = fopen(file_name, opentype); |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
364 _need_close = true; |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
365 } |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
366 |
0 | 367 void fileStream::write(const char* s, size_t len) { |
513
2328d1d3f8cf
6781583: Hotspot build fails on linux 64 bit platform with gcc 4.3.2
xlu
parents:
356
diff
changeset
|
368 if (_file != NULL) { |
2328d1d3f8cf
6781583: Hotspot build fails on linux 64 bit platform with gcc 4.3.2
xlu
parents:
356
diff
changeset
|
369 // Make an unused local variable to avoid warning from gcc 4.x compiler. |
2328d1d3f8cf
6781583: Hotspot build fails on linux 64 bit platform with gcc 4.3.2
xlu
parents:
356
diff
changeset
|
370 size_t count = fwrite(s, 1, len, _file); |
2328d1d3f8cf
6781583: Hotspot build fails on linux 64 bit platform with gcc 4.3.2
xlu
parents:
356
diff
changeset
|
371 } |
0 | 372 update_position(s, len); |
373 } | |
374 | |
2199
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
375 long fileStream::fileSize() { |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
376 long size = -1; |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
377 if (_file != NULL) { |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
378 long pos = ::ftell(_file); |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
379 if (::fseek(_file, 0, SEEK_END) == 0) { |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
380 size = ::ftell(_file); |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
381 } |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
382 ::fseek(_file, pos, SEEK_SET); |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
383 } |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
384 return size; |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
385 } |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
386 |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
387 char* fileStream::readln(char *data, int count ) { |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
388 char * ret = ::fgets(data, count, _file); |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
389 //Get rid of annoying \n char |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
390 data[::strlen(data)-1] = '\0'; |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
391 return ret; |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
392 } |
d8a72fbc4be7
7003401: Implement VM error-reporting functionality on erroneous termination
kamg
parents:
1980
diff
changeset
|
393 |
0 | 394 fileStream::~fileStream() { |
395 if (_file != NULL) { | |
396 if (_need_close) fclose(_file); | |
3767
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
397 _file = NULL; |
0 | 398 } |
399 } | |
400 | |
401 void fileStream::flush() { | |
402 fflush(_file); | |
403 } | |
404 | |
405 fdStream::fdStream(const char* file_name) { | |
406 _fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); | |
407 _need_close = true; | |
408 } | |
409 | |
410 fdStream::~fdStream() { | |
411 if (_fd != -1) { | |
412 if (_need_close) close(_fd); | |
413 _fd = -1; | |
414 } | |
415 } | |
416 | |
417 void fdStream::write(const char* s, size_t len) { | |
513
2328d1d3f8cf
6781583: Hotspot build fails on linux 64 bit platform with gcc 4.3.2
xlu
parents:
356
diff
changeset
|
418 if (_fd != -1) { |
2328d1d3f8cf
6781583: Hotspot build fails on linux 64 bit platform with gcc 4.3.2
xlu
parents:
356
diff
changeset
|
419 // Make an unused local variable to avoid warning from gcc 4.x compiler. |
2328d1d3f8cf
6781583: Hotspot build fails on linux 64 bit platform with gcc 4.3.2
xlu
parents:
356
diff
changeset
|
420 size_t count = ::write(_fd, s, (int)len); |
2328d1d3f8cf
6781583: Hotspot build fails on linux 64 bit platform with gcc 4.3.2
xlu
parents:
356
diff
changeset
|
421 } |
0 | 422 update_position(s, len); |
423 } | |
424 | |
3767
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
425 rotatingFileStream::~rotatingFileStream() { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
426 if (_file != NULL) { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
427 if (_need_close) fclose(_file); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
428 _file = NULL; |
6197 | 429 FREE_C_HEAP_ARRAY(char, _file_name, mtInternal); |
3767
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
430 _file_name = NULL; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
431 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
432 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
433 |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
434 rotatingFileStream::rotatingFileStream(const char* file_name) { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
435 _cur_file_num = 0; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
436 _bytes_writen = 0L; |
6197 | 437 _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); |
3767
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
438 jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
439 _file = fopen(_file_name, "w"); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
440 _need_close = true; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
441 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
442 |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
443 rotatingFileStream::rotatingFileStream(const char* file_name, const char* opentype) { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
444 _cur_file_num = 0; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
445 _bytes_writen = 0L; |
6197 | 446 _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); |
3767
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
447 jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
448 _file = fopen(_file_name, opentype); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
449 _need_close = true; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
450 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
451 |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
452 void rotatingFileStream::write(const char* s, size_t len) { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
453 if (_file != NULL) { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
454 // Make an unused local variable to avoid warning from gcc 4.x compiler. |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
455 size_t count = fwrite(s, 1, len, _file); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
456 Atomic::add((jlong)count, &_bytes_writen); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
457 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
458 update_position(s, len); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
459 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
460 |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
461 // rotate_log must be called from VMThread at safepoint. In case need change parameters |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
462 // for gc log rotation from thread other than VMThread, a sub type of VM_Operation |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
463 // should be created and be submitted to VMThread's operation queue. DO NOT call this |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
464 // function directly. Currently, it is safe to rotate log at safepoint through VMThread. |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
465 // That is, no mutator threads and concurrent GC threads run parallel with VMThread to |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
466 // write to gc log file at safepoint. If in future, changes made for mutator threads or |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
467 // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
468 // must be synchronized. |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
469 void rotatingFileStream::rotate_log() { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
470 if (_bytes_writen < (jlong)GCLogFileSize) return; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
471 #ifdef ASSERT |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
472 Thread *thread = Thread::current(); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
473 assert(thread == NULL || |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
474 (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()), |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
475 "Must be VMThread at safepoint"); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
476 #endif |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
477 if (NumberOfGCLogFiles == 1) { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
478 // rotate in same file |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
479 rewind(); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
480 _bytes_writen = 0L; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
481 return; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
482 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
483 |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
484 // rotate file in names file.0, file.1, file.2, ..., file.<MaxGCLogFileNumbers-1> |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
485 // close current file, rotate to next file |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
486 if (_file != NULL) { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
487 _cur_file_num ++; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
488 if (_cur_file_num >= NumberOfGCLogFiles) _cur_file_num = 0; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
489 jio_snprintf(_file_name, strlen(Arguments::gc_log_filename()) + 10, "%s.%d", |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
490 Arguments::gc_log_filename(), _cur_file_num); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
491 fclose(_file); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
492 _file = NULL; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
493 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
494 _file = fopen(_file_name, "w"); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
495 if (_file != NULL) { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
496 _bytes_writen = 0L; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
497 _need_close = true; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
498 } else { |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
499 tty->print_cr("failed to open rotation log file %s due to %s\n", |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
500 _file_name, strerror(errno)); |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
501 _need_close = false; |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
502 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
503 } |
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
504 |
0 | 505 defaultStream* defaultStream::instance = NULL; |
506 int defaultStream::_output_fd = 1; | |
507 int defaultStream::_error_fd = 2; | |
508 FILE* defaultStream::_output_stream = stdout; | |
509 FILE* defaultStream::_error_stream = stderr; | |
510 | |
511 #define LOG_MAJOR_VERSION 160 | |
512 #define LOG_MINOR_VERSION 1 | |
513 | |
514 void defaultStream::init() { | |
515 _inited = true; | |
516 if (LogVMOutput || LogCompilation) { | |
517 init_log(); | |
518 } | |
519 } | |
520 | |
521 bool defaultStream::has_log_file() { | |
522 // lazily create log file (at startup, LogVMOutput is false even | |
523 // if +LogVMOutput is used, because the flags haven't been parsed yet) | |
524 // For safer printing during fatal error handling, do not init logfile | |
525 // if a VM error has been reported. | |
526 if (!_inited && !is_error_reported()) init(); | |
527 return _log_file != NULL; | |
528 } | |
529 | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
530 static const char* make_log_name(const char* log_name, const char* force_directory) { |
0 | 531 const char* basename = log_name; |
532 char file_sep = os::file_separator()[0]; | |
533 const char* cp; | |
534 for (cp = log_name; *cp != '\0'; cp++) { | |
535 if (*cp == '/' || *cp == file_sep) { | |
536 basename = cp+1; | |
537 } | |
538 } | |
539 const char* nametail = log_name; | |
540 | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
541 // Compute buffer length |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
542 size_t buffer_length; |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
543 if (force_directory != NULL) { |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
544 buffer_length = strlen(force_directory) + strlen(os::file_separator()) + |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
545 strlen(basename) + 1; |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
546 } else { |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
547 buffer_length = strlen(log_name) + 1; |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
548 } |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
549 |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
550 const char* star = strchr(basename, '*'); |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
551 int star_pos = (star == NULL) ? -1 : (star - nametail); |
2400
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
552 int skip = 1; |
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
553 if (star == NULL) { |
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
554 // Try %p |
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
555 star = strstr(basename, "%p"); |
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
556 if (star != NULL) { |
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
557 skip = 2; |
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
558 } |
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
559 } |
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
560 star_pos = (star == NULL) ? -1 : (star - nametail); |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
561 |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
562 char pid[32]; |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
563 if (star_pos >= 0) { |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
564 jio_snprintf(pid, sizeof(pid), "%u", os::current_process_id()); |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
565 buffer_length += strlen(pid); |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
566 } |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
567 |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
568 // Create big enough buffer. |
6197 | 569 char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
570 |
0 | 571 strcpy(buf, ""); |
572 if (force_directory != NULL) { | |
573 strcat(buf, force_directory); | |
574 strcat(buf, os::file_separator()); | |
575 nametail = basename; // completely skip directory prefix | |
576 } | |
577 | |
578 if (star_pos >= 0) { | |
2400
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
579 // convert foo*bar.log or foo%pbar.log to foo123bar.log |
0 | 580 int buf_pos = (int) strlen(buf); |
581 strncpy(&buf[buf_pos], nametail, star_pos); | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
582 strcpy(&buf[buf_pos + star_pos], pid); |
2400
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
583 nametail += star_pos + skip; // skip prefix and pid format |
0 | 584 } |
585 | |
586 strcat(buf, nametail); // append rest of name, or all of name | |
587 return buf; | |
588 } | |
589 | |
590 void defaultStream::init_log() { | |
591 // %%% Need a MutexLocker? | |
592 const char* log_name = LogFile != NULL ? LogFile : "hotspot.log"; | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
593 const char* try_name = make_log_name(log_name, NULL); |
6197 | 594 fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); |
0 | 595 if (!file->is_open()) { |
596 // Try again to open the file. | |
597 char warnbuf[O_BUFLEN*2]; | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
598 jio_snprintf(warnbuf, sizeof(warnbuf), |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
599 "Warning: Cannot open log file: %s\n", try_name); |
0 | 600 // Note: This feature is for maintainer use only. No need for L10N. |
601 jio_print(warnbuf); | |
6197 | 602 FREE_C_HEAP_ARRAY(char, try_name, mtInternal); |
2400
29524004ce17
7022204: LogFile wildcarding should use %p instead of star
never
parents:
2263
diff
changeset
|
603 try_name = make_log_name("hs_pid%p.log", os::get_temp_directory()); |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
604 jio_snprintf(warnbuf, sizeof(warnbuf), |
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
579
diff
changeset
|
605 "Warning: Forcing option -XX:LogFile=%s\n", try_name); |
0 | 606 jio_print(warnbuf); |
607 delete file; | |
6197 | 608 file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); |
609 FREE_C_HEAP_ARRAY(char, try_name, mtInternal); | |
0 | 610 } |
611 if (file->is_open()) { | |
612 _log_file = file; | |
6197 | 613 xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file); |
0 | 614 _outer_xmlStream = xs; |
615 if (this == tty) xtty = xs; | |
616 // Write XML header. | |
617 xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>"); | |
618 // (For now, don't bother to issue a DTD for this private format.) | |
619 jlong time_ms = os::javaTimeMillis() - tty->time_stamp().milliseconds(); | |
620 // %%% Should be: jlong time_ms = os::start_time_milliseconds(), if | |
621 // we ever get round to introduce that method on the os class | |
622 xs->head("hotspot_log version='%d %d'" | |
623 " process='%d' time_ms='"INT64_FORMAT"'", | |
624 LOG_MAJOR_VERSION, LOG_MINOR_VERSION, | |
625 os::current_process_id(), time_ms); | |
626 // Write VM version header immediately. | |
627 xs->head("vm_version"); | |
628 xs->head("name"); xs->text("%s", VM_Version::vm_name()); xs->cr(); | |
629 xs->tail("name"); | |
630 xs->head("release"); xs->text("%s", VM_Version::vm_release()); xs->cr(); | |
631 xs->tail("release"); | |
632 xs->head("info"); xs->text("%s", VM_Version::internal_vm_info_string()); xs->cr(); | |
633 xs->tail("info"); | |
634 xs->tail("vm_version"); | |
635 // Record information about the command-line invocation. | |
636 xs->head("vm_arguments"); // Cf. Arguments::print_on() | |
637 if (Arguments::num_jvm_flags() > 0) { | |
638 xs->head("flags"); | |
639 Arguments::print_jvm_flags_on(xs->text()); | |
640 xs->tail("flags"); | |
641 } | |
642 if (Arguments::num_jvm_args() > 0) { | |
643 xs->head("args"); | |
644 Arguments::print_jvm_args_on(xs->text()); | |
645 xs->tail("args"); | |
646 } | |
647 if (Arguments::java_command() != NULL) { | |
648 xs->head("command"); xs->text()->print_cr("%s", Arguments::java_command()); | |
649 xs->tail("command"); | |
650 } | |
651 if (Arguments::sun_java_launcher() != NULL) { | |
652 xs->head("launcher"); xs->text()->print_cr("%s", Arguments::sun_java_launcher()); | |
653 xs->tail("launcher"); | |
654 } | |
655 if (Arguments::system_properties() != NULL) { | |
656 xs->head("properties"); | |
657 // Print it as a java-style property list. | |
658 // System properties don't generally contain newlines, so don't bother with unparsing. | |
659 for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { | |
660 xs->text()->print_cr("%s=%s", p->key(), p->value()); | |
661 } | |
662 xs->tail("properties"); | |
663 } | |
664 xs->tail("vm_arguments"); | |
665 // tty output per se is grouped under the <tty>...</tty> element. | |
666 xs->head("tty"); | |
667 // All further non-markup text gets copied to the tty: | |
668 xs->_text = this; // requires friend declaration! | |
669 } else { | |
670 delete(file); | |
671 // and leave xtty as NULL | |
672 LogVMOutput = false; | |
673 DisplayVMOutput = true; | |
674 LogCompilation = false; | |
675 } | |
676 } | |
677 | |
678 // finish_log() is called during normal VM shutdown. finish_log_on_error() is | |
679 // called by ostream_abort() after a fatal error. | |
680 // | |
681 void defaultStream::finish_log() { | |
682 xmlStream* xs = _outer_xmlStream; | |
683 xs->done("tty"); | |
684 | |
685 // Other log forks are appended here, at the End of Time: | |
686 CompileLog::finish_log(xs->out()); // write compile logging, if any, now | |
687 | |
688 xs->done("hotspot_log"); | |
689 xs->flush(); | |
690 | |
691 fileStream* file = _log_file; | |
692 _log_file = NULL; | |
693 | |
694 delete _outer_xmlStream; | |
695 _outer_xmlStream = NULL; | |
696 | |
697 file->flush(); | |
698 delete file; | |
699 } | |
700 | |
701 void defaultStream::finish_log_on_error(char *buf, int buflen) { | |
702 xmlStream* xs = _outer_xmlStream; | |
703 | |
704 if (xs && xs->out()) { | |
705 | |
706 xs->done_raw("tty"); | |
707 | |
708 // Other log forks are appended here, at the End of Time: | |
709 CompileLog::finish_log_on_error(xs->out(), buf, buflen); // write compile logging, if any, now | |
710 | |
711 xs->done_raw("hotspot_log"); | |
712 xs->flush(); | |
713 | |
714 fileStream* file = _log_file; | |
715 _log_file = NULL; | |
716 _outer_xmlStream = NULL; | |
717 | |
718 if (file) { | |
719 file->flush(); | |
720 | |
721 // Can't delete or close the file because delete and fclose aren't | |
722 // async-safe. We are about to die, so leave it to the kernel. | |
723 // delete file; | |
724 } | |
725 } | |
726 } | |
727 | |
728 intx defaultStream::hold(intx writer_id) { | |
729 bool has_log = has_log_file(); // check before locking | |
730 if (// impossible, but who knows? | |
731 writer_id == NO_WRITER || | |
732 | |
733 // bootstrap problem | |
734 tty_lock == NULL || | |
735 | |
736 // can't grab a lock or call Thread::current() if TLS isn't initialized | |
737 ThreadLocalStorage::thread() == NULL || | |
738 | |
739 // developer hook | |
740 !SerializeVMOutput || | |
741 | |
742 // VM already unhealthy | |
743 is_error_reported() || | |
744 | |
745 // safepoint == global lock (for VM only) | |
746 (SafepointSynchronize::is_synchronizing() && | |
747 Thread::current()->is_VM_thread()) | |
748 ) { | |
749 // do not attempt to lock unless we know the thread and the VM is healthy | |
750 return NO_WRITER; | |
751 } | |
752 if (_writer == writer_id) { | |
753 // already held, no need to re-grab the lock | |
754 return NO_WRITER; | |
755 } | |
756 tty_lock->lock_without_safepoint_check(); | |
757 // got the lock | |
758 if (writer_id != _last_writer) { | |
759 if (has_log) { | |
760 _log_file->bol(); | |
761 // output a hint where this output is coming from: | |
762 _log_file->print_cr("<writer thread='"INTX_FORMAT"'/>", writer_id); | |
763 } | |
764 _last_writer = writer_id; | |
765 } | |
766 _writer = writer_id; | |
767 return writer_id; | |
768 } | |
769 | |
770 void defaultStream::release(intx holder) { | |
771 if (holder == NO_WRITER) { | |
772 // nothing to release: either a recursive lock, or we scribbled (too bad) | |
773 return; | |
774 } | |
775 if (_writer != holder) { | |
776 return; // already unlocked, perhaps via break_tty_lock_for_safepoint | |
777 } | |
778 _writer = NO_WRITER; | |
779 tty_lock->unlock(); | |
780 } | |
781 | |
782 | |
783 // Yuck: jio_print does not accept char*/len. | |
784 static void call_jio_print(const char* s, size_t len) { | |
785 char buffer[O_BUFLEN+100]; | |
786 if (len > sizeof(buffer)-1) { | |
787 warning("increase O_BUFLEN in ostream.cpp -- output truncated"); | |
788 len = sizeof(buffer)-1; | |
789 } | |
790 strncpy(buffer, s, len); | |
791 buffer[len] = '\0'; | |
792 jio_print(buffer); | |
793 } | |
794 | |
795 | |
796 void defaultStream::write(const char* s, size_t len) { | |
797 intx thread_id = os::current_thread_id(); | |
798 intx holder = hold(thread_id); | |
799 | |
800 if (DisplayVMOutput && | |
801 (_outer_xmlStream == NULL || !_outer_xmlStream->inside_attrs())) { | |
802 // print to output stream. It can be redirected by a vfprintf hook | |
803 if (s[len] == '\0') { | |
804 jio_print(s); | |
805 } else { | |
806 call_jio_print(s, len); | |
807 } | |
808 } | |
809 | |
810 // print to log file | |
811 if (has_log_file()) { | |
812 int nl0 = _newlines; | |
813 xmlTextStream::write(s, len); | |
814 // flush the log file too, if there were any newlines | |
815 if (nl0 != _newlines){ | |
816 flush(); | |
817 } | |
818 } else { | |
819 update_position(s, len); | |
820 } | |
821 | |
822 release(holder); | |
823 } | |
824 | |
825 intx ttyLocker::hold_tty() { | |
826 if (defaultStream::instance == NULL) return defaultStream::NO_WRITER; | |
827 intx thread_id = os::current_thread_id(); | |
828 return defaultStream::instance->hold(thread_id); | |
829 } | |
830 | |
831 void ttyLocker::release_tty(intx holder) { | |
832 if (holder == defaultStream::NO_WRITER) return; | |
833 defaultStream::instance->release(holder); | |
834 } | |
835 | |
2263
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
836 bool ttyLocker::release_tty_if_locked() { |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
837 intx thread_id = os::current_thread_id(); |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
838 if (defaultStream::instance->writer() == thread_id) { |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
839 // release the lock and return true so callers know if was |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
840 // previously held. |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
841 release_tty(thread_id); |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
842 return true; |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
843 } |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
844 return false; |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
845 } |
5841dc1964f0
7021531: lock ordering problems after fix for 6354181
never
parents:
2199
diff
changeset
|
846 |
0 | 847 void ttyLocker::break_tty_lock_for_safepoint(intx holder) { |
848 if (defaultStream::instance != NULL && | |
849 defaultStream::instance->writer() == holder) { | |
850 if (xtty != NULL) { | |
851 xtty->print_cr("<!-- safepoint while printing -->"); | |
852 } | |
853 defaultStream::instance->release(holder); | |
854 } | |
855 // (else there was no lock to break) | |
856 } | |
857 | |
858 void ostream_init() { | |
859 if (defaultStream::instance == NULL) { | |
6197 | 860 defaultStream::instance = new(ResourceObj::C_HEAP, mtInternal) defaultStream(); |
0 | 861 tty = defaultStream::instance; |
862 | |
863 // We want to ensure that time stamps in GC logs consider time 0 | |
864 // the time when the JVM is initialized, not the first time we ask | |
865 // for a time stamp. So, here, we explicitly update the time stamp | |
866 // of tty. | |
867 tty->time_stamp().update_to(1); | |
868 } | |
869 } | |
870 | |
871 void ostream_init_log() { | |
872 // For -Xloggc:<file> option - called in runtime/thread.cpp | |
873 // Note : this must be called AFTER ostream_init() | |
874 | |
875 gclog_or_tty = tty; // default to tty | |
876 if (Arguments::gc_log_filename() != NULL) { | |
3767
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
877 fileStream * gclog = UseGCLogFileRotation ? |
6197 | 878 new(ResourceObj::C_HEAP, mtInternal) |
3767
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
879 rotatingFileStream(Arguments::gc_log_filename()) : |
6197 | 880 new(ResourceObj::C_HEAP, mtInternal) |
3767
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
881 fileStream(Arguments::gc_log_filename()); |
0 | 882 if (gclog->is_open()) { |
883 // now we update the time stamp of the GC log to be synced up | |
884 // with tty. | |
885 gclog->time_stamp().update_to(tty->time_stamp().ticks()); | |
886 } | |
3767
2a241e764894
6941923: RFE: Handling large log files produced by long running Java Applications
minqi
parents:
2420
diff
changeset
|
887 gclog_or_tty = gclog; |
0 | 888 } |
889 | |
890 // If we haven't lazily initialized the logfile yet, do it now, | |
891 // to avoid the possibility of lazy initialization during a VM | |
892 // crash, which can affect the stability of the fatal error handler. | |
893 defaultStream::instance->has_log_file(); | |
894 } | |
895 | |
896 // ostream_exit() is called during normal VM exit to finish log files, flush | |
897 // output and free resource. | |
898 void ostream_exit() { | |
899 static bool ostream_exit_called = false; | |
900 if (ostream_exit_called) return; | |
901 ostream_exit_called = true; | |
902 if (gclog_or_tty != tty) { | |
903 delete gclog_or_tty; | |
904 } | |
905 { | |
906 // we temporaly disable PrintMallocFree here | |
907 // as otherwise it'll lead to using of almost deleted | |
908 // tty or defaultStream::instance in logging facility | |
909 // of HeapFree(), see 6391258 | |
910 DEBUG_ONLY(FlagSetting fs(PrintMallocFree, false);) | |
911 if (tty != defaultStream::instance) { | |
912 delete tty; | |
913 } | |
914 if (defaultStream::instance != NULL) { | |
915 delete defaultStream::instance; | |
916 } | |
917 } | |
918 tty = NULL; | |
919 xtty = NULL; | |
920 gclog_or_tty = NULL; | |
921 defaultStream::instance = NULL; | |
922 } | |
923 | |
924 // ostream_abort() is called by os::abort() when VM is about to die. | |
925 void ostream_abort() { | |
926 // Here we can't delete gclog_or_tty and tty, just flush their output | |
927 if (gclog_or_tty) gclog_or_tty->flush(); | |
928 if (tty) tty->flush(); | |
929 | |
930 if (defaultStream::instance != NULL) { | |
931 static char buf[4096]; | |
932 defaultStream::instance->finish_log_on_error(buf, sizeof(buf)); | |
933 } | |
934 } | |
935 | |
936 staticBufferStream::staticBufferStream(char* buffer, size_t buflen, | |
937 outputStream *outer_stream) { | |
938 _buffer = buffer; | |
939 _buflen = buflen; | |
940 _outer_stream = outer_stream; | |
2420
8010c8c623ac
7032849: 7022998 changes broke hs_err compile task print
kvn
parents:
2400
diff
changeset
|
941 // compile task prints time stamp relative to VM start |
8010c8c623ac
7032849: 7022998 changes broke hs_err compile task print
kvn
parents:
2400
diff
changeset
|
942 _stamp.update_to(1); |
0 | 943 } |
944 | |
945 void staticBufferStream::write(const char* c, size_t len) { | |
946 _outer_stream->print_raw(c, (int)len); | |
947 } | |
948 | |
949 void staticBufferStream::flush() { | |
950 _outer_stream->flush(); | |
951 } | |
952 | |
953 void staticBufferStream::print(const char* format, ...) { | |
954 va_list ap; | |
955 va_start(ap, format); | |
956 size_t len; | |
957 const char* str = do_vsnprintf(_buffer, _buflen, format, ap, false, len); | |
958 write(str, len); | |
959 va_end(ap); | |
960 } | |
961 | |
962 void staticBufferStream::print_cr(const char* format, ...) { | |
963 va_list ap; | |
964 va_start(ap, format); | |
965 size_t len; | |
966 const char* str = do_vsnprintf(_buffer, _buflen, format, ap, true, len); | |
967 write(str, len); | |
968 va_end(ap); | |
969 } | |
970 | |
971 void staticBufferStream::vprint(const char *format, va_list argptr) { | |
972 size_t len; | |
973 const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, false, len); | |
974 write(str, len); | |
975 } | |
976 | |
977 void staticBufferStream::vprint_cr(const char* format, va_list argptr) { | |
978 size_t len; | |
979 const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, true, len); | |
980 write(str, len); | |
981 } | |
982 | |
222 | 983 bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStream() { |
0 | 984 buffer_length = initial_size; |
6197 | 985 buffer = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); |
0 | 986 buffer_pos = 0; |
987 buffer_fixed = false; | |
222 | 988 buffer_max = bufmax; |
0 | 989 } |
990 | |
222 | 991 bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax) : outputStream() { |
0 | 992 buffer_length = fixed_buffer_size; |
993 buffer = fixed_buffer; | |
994 buffer_pos = 0; | |
995 buffer_fixed = true; | |
222 | 996 buffer_max = bufmax; |
0 | 997 } |
998 | |
999 void bufferedStream::write(const char* s, size_t len) { | |
222 | 1000 |
1001 if(buffer_pos + len > buffer_max) { | |
1002 flush(); | |
1003 } | |
1004 | |
0 | 1005 size_t end = buffer_pos + len; |
1006 if (end >= buffer_length) { | |
1007 if (buffer_fixed) { | |
1008 // if buffer cannot resize, silently truncate | |
1009 len = buffer_length - buffer_pos - 1; | |
1010 } else { | |
1011 // For small overruns, double the buffer. For larger ones, | |
1012 // increase to the requested size. | |
1013 if (end < buffer_length * 2) { | |
1014 end = buffer_length * 2; | |
1015 } | |
6197 | 1016 buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end, mtInternal); |
0 | 1017 buffer_length = end; |
1018 } | |
1019 } | |
1020 memcpy(buffer + buffer_pos, s, len); | |
1021 buffer_pos += len; | |
1022 update_position(s, len); | |
1023 } | |
1024 | |
1025 char* bufferedStream::as_string() { | |
1026 char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1); | |
1027 strncpy(copy, buffer, buffer_pos); | |
1028 copy[buffer_pos] = 0; // terminating null | |
1029 return copy; | |
1030 } | |
1031 | |
1032 bufferedStream::~bufferedStream() { | |
1033 if (!buffer_fixed) { | |
6197 | 1034 FREE_C_HEAP_ARRAY(char, buffer, mtInternal); |
0 | 1035 } |
1036 } | |
1037 | |
1038 #ifndef PRODUCT | |
1039 | |
3960 | 1040 #if defined(SOLARIS) || defined(LINUX) || defined(_ALLBSD_SOURCE) |
0 | 1041 #include <sys/types.h> |
1042 #include <sys/socket.h> | |
1043 #include <netinet/in.h> | |
1044 #include <arpa/inet.h> | |
1045 #endif | |
1046 | |
1047 // Network access | |
222 | 1048 networkStream::networkStream() : bufferedStream(1024*10, 1024*10) { |
0 | 1049 |
1050 _socket = -1; | |
1051 | |
1980
828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
ikrylov
parents:
1972
diff
changeset
|
1052 int result = os::socket(AF_INET, SOCK_STREAM, 0); |
0 | 1053 if (result <= 0) { |
1054 assert(false, "Socket could not be created!"); | |
1055 } else { | |
1056 _socket = result; | |
1057 } | |
1058 } | |
1059 | |
1060 int networkStream::read(char *buf, size_t len) { | |
1980
828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
ikrylov
parents:
1972
diff
changeset
|
1061 return os::recv(_socket, buf, (int)len, 0); |
0 | 1062 } |
1063 | |
1064 void networkStream::flush() { | |
1065 if (size() != 0) { | |
4717
11c26bfcf8c7
7091417: recvfrom's 6th input should be of type socklen_t
phh
parents:
3960
diff
changeset
|
1066 int result = os::raw_send(_socket, (char *)base(), size(), 0); |
222 | 1067 assert(result != -1, "connection error"); |
1068 assert(result == (int)size(), "didn't send enough data"); | |
0 | 1069 } |
1070 reset(); | |
1071 } | |
1072 | |
1073 networkStream::~networkStream() { | |
1074 close(); | |
1075 } | |
1076 | |
1077 void networkStream::close() { | |
1078 if (_socket != -1) { | |
1079 flush(); | |
1980
828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
ikrylov
parents:
1972
diff
changeset
|
1080 os::socket_close(_socket); |
0 | 1081 _socket = -1; |
1082 } | |
1083 } | |
1084 | |
1085 bool networkStream::connect(const char *ip, short port) { | |
1086 | |
1087 struct sockaddr_in server; | |
1088 server.sin_family = AF_INET; | |
1089 server.sin_port = htons(port); | |
1090 | |
1091 server.sin_addr.s_addr = inet_addr(ip); | |
80
092ea87cc974
6679422: networkStream::connect() in ostream.cpp is not 64-bit clean
jcoomes
parents:
0
diff
changeset
|
1092 if (server.sin_addr.s_addr == (uint32_t)-1) { |
1980
828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
ikrylov
parents:
1972
diff
changeset
|
1093 struct hostent* host = os::get_host_by_name((char*)ip); |
0 | 1094 if (host != NULL) { |
1095 memcpy(&server.sin_addr, host->h_addr_list[0], host->h_length); | |
1096 } else { | |
1097 return false; | |
1098 } | |
1099 } | |
1100 | |
1101 | |
1980
828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
ikrylov
parents:
1972
diff
changeset
|
1102 int result = os::connect(_socket, (struct sockaddr*)&server, sizeof(struct sockaddr_in)); |
0 | 1103 return (result >= 0); |
1104 } | |
1105 | |
1106 #endif |