1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/utilities/ostream.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,1326 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "compiler/compileLog.hpp" 1.30 +#include "oops/oop.inline.hpp" 1.31 +#include "runtime/arguments.hpp" 1.32 +#include "utilities/defaultStream.hpp" 1.33 +#include "utilities/ostream.hpp" 1.34 +#include "utilities/top.hpp" 1.35 +#include "utilities/xmlstream.hpp" 1.36 +#ifdef TARGET_OS_FAMILY_linux 1.37 +# include "os_linux.inline.hpp" 1.38 +#endif 1.39 +#ifdef TARGET_OS_FAMILY_solaris 1.40 +# include "os_solaris.inline.hpp" 1.41 +#endif 1.42 +#ifdef TARGET_OS_FAMILY_windows 1.43 +# include "os_windows.inline.hpp" 1.44 +#endif 1.45 +#ifdef TARGET_OS_FAMILY_aix 1.46 +# include "os_aix.inline.hpp" 1.47 +#endif 1.48 +#ifdef TARGET_OS_FAMILY_bsd 1.49 +# include "os_bsd.inline.hpp" 1.50 +#endif 1.51 + 1.52 +extern "C" void jio_print(const char* s); // Declarationtion of jvm method 1.53 + 1.54 +outputStream::outputStream(int width) { 1.55 + _width = width; 1.56 + _position = 0; 1.57 + _newlines = 0; 1.58 + _precount = 0; 1.59 + _indentation = 0; 1.60 +} 1.61 + 1.62 +outputStream::outputStream(int width, bool has_time_stamps) { 1.63 + _width = width; 1.64 + _position = 0; 1.65 + _newlines = 0; 1.66 + _precount = 0; 1.67 + _indentation = 0; 1.68 + if (has_time_stamps) _stamp.update(); 1.69 +} 1.70 + 1.71 +void outputStream::update_position(const char* s, size_t len) { 1.72 + for (size_t i = 0; i < len; i++) { 1.73 + char ch = s[i]; 1.74 + if (ch == '\n') { 1.75 + _newlines += 1; 1.76 + _precount += _position + 1; 1.77 + _position = 0; 1.78 + } else if (ch == '\t') { 1.79 + int tw = 8 - (_position & 7); 1.80 + _position += tw; 1.81 + _precount -= tw-1; // invariant: _precount + _position == total count 1.82 + } else { 1.83 + _position += 1; 1.84 + } 1.85 + } 1.86 +} 1.87 + 1.88 +// Execute a vsprintf, using the given buffer if necessary. 1.89 +// Return a pointer to the formatted string. 1.90 +const char* outputStream::do_vsnprintf(char* buffer, size_t buflen, 1.91 + const char* format, va_list ap, 1.92 + bool add_cr, 1.93 + size_t& result_len) { 1.94 + const char* result; 1.95 + if (add_cr) buflen--; 1.96 + if (!strchr(format, '%')) { 1.97 + // constant format string 1.98 + result = format; 1.99 + result_len = strlen(result); 1.100 + if (add_cr && result_len >= buflen) result_len = buflen-1; // truncate 1.101 + } else if (format[0] == '%' && format[1] == 's' && format[2] == '\0') { 1.102 + // trivial copy-through format string 1.103 + result = va_arg(ap, const char*); 1.104 + result_len = strlen(result); 1.105 + if (add_cr && result_len >= buflen) result_len = buflen-1; // truncate 1.106 + } else if (vsnprintf(buffer, buflen, format, ap) >= 0) { 1.107 + result = buffer; 1.108 + result_len = strlen(result); 1.109 + } else { 1.110 + DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");) 1.111 + result = buffer; 1.112 + result_len = buflen - 1; 1.113 + buffer[result_len] = 0; 1.114 + } 1.115 + if (add_cr) { 1.116 + if (result != buffer) { 1.117 + strncpy(buffer, result, buflen); 1.118 + result = buffer; 1.119 + } 1.120 + buffer[result_len++] = '\n'; 1.121 + buffer[result_len] = 0; 1.122 + } 1.123 + return result; 1.124 +} 1.125 + 1.126 +void outputStream::print(const char* format, ...) { 1.127 + char buffer[O_BUFLEN]; 1.128 + va_list ap; 1.129 + va_start(ap, format); 1.130 + size_t len; 1.131 + const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, false, len); 1.132 + write(str, len); 1.133 + va_end(ap); 1.134 +} 1.135 + 1.136 +void outputStream::print_cr(const char* format, ...) { 1.137 + char buffer[O_BUFLEN]; 1.138 + va_list ap; 1.139 + va_start(ap, format); 1.140 + size_t len; 1.141 + const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, true, len); 1.142 + write(str, len); 1.143 + va_end(ap); 1.144 +} 1.145 + 1.146 +void outputStream::vprint(const char *format, va_list argptr) { 1.147 + char buffer[O_BUFLEN]; 1.148 + size_t len; 1.149 + const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, false, len); 1.150 + write(str, len); 1.151 +} 1.152 + 1.153 +void outputStream::vprint_cr(const char* format, va_list argptr) { 1.154 + char buffer[O_BUFLEN]; 1.155 + size_t len; 1.156 + const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, true, len); 1.157 + write(str, len); 1.158 +} 1.159 + 1.160 +void outputStream::fill_to(int col) { 1.161 + int need_fill = col - position(); 1.162 + sp(need_fill); 1.163 +} 1.164 + 1.165 +void outputStream::move_to(int col, int slop, int min_space) { 1.166 + if (position() >= col + slop) 1.167 + cr(); 1.168 + int need_fill = col - position(); 1.169 + if (need_fill < min_space) 1.170 + need_fill = min_space; 1.171 + sp(need_fill); 1.172 +} 1.173 + 1.174 +void outputStream::put(char ch) { 1.175 + assert(ch != 0, "please fix call site"); 1.176 + char buf[] = { ch, '\0' }; 1.177 + write(buf, 1); 1.178 +} 1.179 + 1.180 +#define SP_USE_TABS false 1.181 + 1.182 +void outputStream::sp(int count) { 1.183 + if (count < 0) return; 1.184 + if (SP_USE_TABS && count >= 8) { 1.185 + int target = position() + count; 1.186 + while (count >= 8) { 1.187 + this->write("\t", 1); 1.188 + count -= 8; 1.189 + } 1.190 + count = target - position(); 1.191 + } 1.192 + while (count > 0) { 1.193 + int nw = (count > 8) ? 8 : count; 1.194 + this->write(" ", nw); 1.195 + count -= nw; 1.196 + } 1.197 +} 1.198 + 1.199 +void outputStream::cr() { 1.200 + this->write("\n", 1); 1.201 +} 1.202 + 1.203 +void outputStream::stamp() { 1.204 + if (! _stamp.is_updated()) { 1.205 + _stamp.update(); // start at 0 on first call to stamp() 1.206 + } 1.207 + 1.208 + // outputStream::stamp() may get called by ostream_abort(), use snprintf 1.209 + // to avoid allocating large stack buffer in print(). 1.210 + char buf[40]; 1.211 + jio_snprintf(buf, sizeof(buf), "%.3f", _stamp.seconds()); 1.212 + print_raw(buf); 1.213 +} 1.214 + 1.215 +void outputStream::stamp(bool guard, 1.216 + const char* prefix, 1.217 + const char* suffix) { 1.218 + if (!guard) { 1.219 + return; 1.220 + } 1.221 + print_raw(prefix); 1.222 + stamp(); 1.223 + print_raw(suffix); 1.224 +} 1.225 + 1.226 +void outputStream::date_stamp(bool guard, 1.227 + const char* prefix, 1.228 + const char* suffix) { 1.229 + if (!guard) { 1.230 + return; 1.231 + } 1.232 + print_raw(prefix); 1.233 + static const char error_time[] = "yyyy-mm-ddThh:mm:ss.mmm+zzzz"; 1.234 + static const int buffer_length = 32; 1.235 + char buffer[buffer_length]; 1.236 + const char* iso8601_result = os::iso8601_time(buffer, buffer_length); 1.237 + if (iso8601_result != NULL) { 1.238 + print_raw(buffer); 1.239 + } else { 1.240 + print_raw(error_time); 1.241 + } 1.242 + print_raw(suffix); 1.243 + return; 1.244 +} 1.245 + 1.246 +outputStream& outputStream::indent() { 1.247 + while (_position < _indentation) sp(); 1.248 + return *this; 1.249 +} 1.250 + 1.251 +void outputStream::print_jlong(jlong value) { 1.252 + print(JLONG_FORMAT, value); 1.253 +} 1.254 + 1.255 +void outputStream::print_julong(julong value) { 1.256 + print(JULONG_FORMAT, value); 1.257 +} 1.258 + 1.259 +/** 1.260 + * This prints out hex data in a 'windbg' or 'xxd' form, where each line is: 1.261 + * <hex-address>: 8 * <hex-halfword> <ascii translation (optional)> 1.262 + * example: 1.263 + * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000 .DOF............ 1.264 + * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005 .......@... .... 1.265 + * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......] 1.266 + * ... 1.267 + * 1.268 + * indent is applied to each line. Ends with a CR. 1.269 + */ 1.270 +void outputStream::print_data(void* data, size_t len, bool with_ascii) { 1.271 + size_t limit = (len + 16) / 16 * 16; 1.272 + for (size_t i = 0; i < limit; ++i) { 1.273 + if (i % 16 == 0) { 1.274 + indent().print(SIZE_FORMAT_HEX_W(07)":", i); 1.275 + } 1.276 + if (i % 2 == 0) { 1.277 + print(" "); 1.278 + } 1.279 + if (i < len) { 1.280 + print("%02x", ((unsigned char*)data)[i]); 1.281 + } else { 1.282 + print(" "); 1.283 + } 1.284 + if ((i + 1) % 16 == 0) { 1.285 + if (with_ascii) { 1.286 + print(" "); 1.287 + for (size_t j = 0; j < 16; ++j) { 1.288 + size_t idx = i + j - 15; 1.289 + if (idx < len) { 1.290 + char c = ((char*)data)[idx]; 1.291 + print("%c", c >= 32 && c <= 126 ? c : '.'); 1.292 + } 1.293 + } 1.294 + } 1.295 + cr(); 1.296 + } 1.297 + } 1.298 +} 1.299 + 1.300 +stringStream::stringStream(size_t initial_size) : outputStream() { 1.301 + buffer_length = initial_size; 1.302 + buffer = NEW_RESOURCE_ARRAY(char, buffer_length); 1.303 + buffer_pos = 0; 1.304 + buffer_fixed = false; 1.305 + DEBUG_ONLY(rm = Thread::current()->current_resource_mark();) 1.306 +} 1.307 + 1.308 +// useful for output to fixed chunks of memory, such as performance counters 1.309 +stringStream::stringStream(char* fixed_buffer, size_t fixed_buffer_size) : outputStream() { 1.310 + buffer_length = fixed_buffer_size; 1.311 + buffer = fixed_buffer; 1.312 + buffer_pos = 0; 1.313 + buffer_fixed = true; 1.314 +} 1.315 + 1.316 +void stringStream::write(const char* s, size_t len) { 1.317 + size_t write_len = len; // number of non-null bytes to write 1.318 + size_t end = buffer_pos + len + 1; // position after write and final '\0' 1.319 + if (end > buffer_length) { 1.320 + if (buffer_fixed) { 1.321 + // if buffer cannot resize, silently truncate 1.322 + end = buffer_length; 1.323 + write_len = end - buffer_pos - 1; // leave room for the final '\0' 1.324 + } else { 1.325 + // For small overruns, double the buffer. For larger ones, 1.326 + // increase to the requested size. 1.327 + if (end < buffer_length * 2) { 1.328 + end = buffer_length * 2; 1.329 + } 1.330 + char* oldbuf = buffer; 1.331 + assert(rm == NULL || Thread::current()->current_resource_mark() == rm, 1.332 + "stringStream is re-allocated with a different ResourceMark"); 1.333 + buffer = NEW_RESOURCE_ARRAY(char, end); 1.334 + strncpy(buffer, oldbuf, buffer_pos); 1.335 + buffer_length = end; 1.336 + } 1.337 + } 1.338 + // invariant: buffer is always null-terminated 1.339 + guarantee(buffer_pos + write_len + 1 <= buffer_length, "stringStream oob"); 1.340 + buffer[buffer_pos + write_len] = 0; 1.341 + strncpy(buffer + buffer_pos, s, write_len); 1.342 + buffer_pos += write_len; 1.343 + 1.344 + // Note that the following does not depend on write_len. 1.345 + // This means that position and count get updated 1.346 + // even when overflow occurs. 1.347 + update_position(s, len); 1.348 +} 1.349 + 1.350 +char* stringStream::as_string() { 1.351 + char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos + 1); 1.352 + strncpy(copy, buffer, buffer_pos); 1.353 + copy[buffer_pos] = 0; // terminating null 1.354 + return copy; 1.355 +} 1.356 + 1.357 +stringStream::~stringStream() {} 1.358 + 1.359 +xmlStream* xtty; 1.360 +outputStream* tty; 1.361 +outputStream* gclog_or_tty; 1.362 +extern Mutex* tty_lock; 1.363 + 1.364 +#define EXTRACHARLEN 32 1.365 +#define CURRENTAPPX ".current" 1.366 +#define FILENAMEBUFLEN 1024 1.367 +// convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS 1.368 +char* get_datetime_string(char *buf, size_t len) { 1.369 + os::local_time_string(buf, len); 1.370 + int i = (int)strlen(buf); 1.371 + while (i-- >= 0) { 1.372 + if (buf[i] == ' ') buf[i] = '_'; 1.373 + else if (buf[i] == ':') buf[i] = '-'; 1.374 + } 1.375 + return buf; 1.376 +} 1.377 + 1.378 +static const char* make_log_name_internal(const char* log_name, const char* force_directory, 1.379 + int pid, const char* tms) { 1.380 + const char* basename = log_name; 1.381 + char file_sep = os::file_separator()[0]; 1.382 + const char* cp; 1.383 + char pid_text[32]; 1.384 + 1.385 + for (cp = log_name; *cp != '\0'; cp++) { 1.386 + if (*cp == '/' || *cp == file_sep) { 1.387 + basename = cp + 1; 1.388 + } 1.389 + } 1.390 + const char* nametail = log_name; 1.391 + // Compute buffer length 1.392 + size_t buffer_length; 1.393 + if (force_directory != NULL) { 1.394 + buffer_length = strlen(force_directory) + strlen(os::file_separator()) + 1.395 + strlen(basename) + 1; 1.396 + } else { 1.397 + buffer_length = strlen(log_name) + 1; 1.398 + } 1.399 + 1.400 + // const char* star = strchr(basename, '*'); 1.401 + const char* pts = strstr(basename, "%p"); 1.402 + int pid_pos = (pts == NULL) ? -1 : (pts - nametail); 1.403 + 1.404 + if (pid_pos >= 0) { 1.405 + jio_snprintf(pid_text, sizeof(pid_text), "pid%u", pid); 1.406 + buffer_length += strlen(pid_text); 1.407 + } 1.408 + 1.409 + pts = strstr(basename, "%t"); 1.410 + int tms_pos = (pts == NULL) ? -1 : (pts - nametail); 1.411 + if (tms_pos >= 0) { 1.412 + buffer_length += strlen(tms); 1.413 + } 1.414 + 1.415 + // Create big enough buffer. 1.416 + char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); 1.417 + 1.418 + strcpy(buf, ""); 1.419 + if (force_directory != NULL) { 1.420 + strcat(buf, force_directory); 1.421 + strcat(buf, os::file_separator()); 1.422 + nametail = basename; // completely skip directory prefix 1.423 + } 1.424 + 1.425 + // who is first, %p or %t? 1.426 + int first = -1, second = -1; 1.427 + const char *p1st = NULL; 1.428 + const char *p2nd = NULL; 1.429 + 1.430 + if (pid_pos >= 0 && tms_pos >= 0) { 1.431 + // contains both %p and %t 1.432 + if (pid_pos < tms_pos) { 1.433 + // case foo%pbar%tmonkey.log 1.434 + first = pid_pos; 1.435 + p1st = pid_text; 1.436 + second = tms_pos; 1.437 + p2nd = tms; 1.438 + } else { 1.439 + // case foo%tbar%pmonkey.log 1.440 + first = tms_pos; 1.441 + p1st = tms; 1.442 + second = pid_pos; 1.443 + p2nd = pid_text; 1.444 + } 1.445 + } else if (pid_pos >= 0) { 1.446 + // contains %p only 1.447 + first = pid_pos; 1.448 + p1st = pid_text; 1.449 + } else if (tms_pos >= 0) { 1.450 + // contains %t only 1.451 + first = tms_pos; 1.452 + p1st = tms; 1.453 + } 1.454 + 1.455 + int buf_pos = (int)strlen(buf); 1.456 + const char* tail = nametail; 1.457 + 1.458 + if (first >= 0) { 1.459 + tail = nametail + first + 2; 1.460 + strncpy(&buf[buf_pos], nametail, first); 1.461 + strcpy(&buf[buf_pos + first], p1st); 1.462 + buf_pos = (int)strlen(buf); 1.463 + if (second >= 0) { 1.464 + strncpy(&buf[buf_pos], tail, second - first - 2); 1.465 + strcpy(&buf[buf_pos + second - first - 2], p2nd); 1.466 + tail = nametail + second + 2; 1.467 + } 1.468 + } 1.469 + strcat(buf, tail); // append rest of name, or all of name 1.470 + return buf; 1.471 +} 1.472 + 1.473 +// log_name comes from -XX:LogFile=log_name or -Xloggc:log_name 1.474 +// in log_name, %p => pid1234 and 1.475 +// %t => YYYY-MM-DD_HH-MM-SS 1.476 +static const char* make_log_name(const char* log_name, const char* force_directory) { 1.477 + char timestr[32]; 1.478 + get_datetime_string(timestr, sizeof(timestr)); 1.479 + return make_log_name_internal(log_name, force_directory, os::current_process_id(), 1.480 + timestr); 1.481 +} 1.482 + 1.483 +#ifndef PRODUCT 1.484 +void test_loggc_filename() { 1.485 + int pid; 1.486 + char tms[32]; 1.487 + char i_result[FILENAMEBUFLEN]; 1.488 + const char* o_result; 1.489 + get_datetime_string(tms, sizeof(tms)); 1.490 + pid = os::current_process_id(); 1.491 + 1.492 + // test.log 1.493 + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test.log", tms); 1.494 + o_result = make_log_name_internal("test.log", NULL, pid, tms); 1.495 + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)"); 1.496 + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); 1.497 + 1.498 + // test-%t-%p.log 1.499 + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%s-pid%u.log", tms, pid); 1.500 + o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms); 1.501 + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)"); 1.502 + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); 1.503 + 1.504 + // test-%t%p.log 1.505 + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%spid%u.log", tms, pid); 1.506 + o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms); 1.507 + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)"); 1.508 + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); 1.509 + 1.510 + // %p%t.log 1.511 + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u%s.log", pid, tms); 1.512 + o_result = make_log_name_internal("%p%t.log", NULL, pid, tms); 1.513 + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)"); 1.514 + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); 1.515 + 1.516 + // %p-test.log 1.517 + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u-test.log", pid); 1.518 + o_result = make_log_name_internal("%p-test.log", NULL, pid, tms); 1.519 + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)"); 1.520 + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); 1.521 + 1.522 + // %t.log 1.523 + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "%s.log", tms); 1.524 + o_result = make_log_name_internal("%t.log", NULL, pid, tms); 1.525 + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)"); 1.526 + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); 1.527 +} 1.528 +#endif // PRODUCT 1.529 + 1.530 +fileStream::fileStream(const char* file_name) { 1.531 + _file = fopen(file_name, "w"); 1.532 + if (_file != NULL) { 1.533 + _need_close = true; 1.534 + } else { 1.535 + warning("Cannot open file %s due to %s\n", file_name, strerror(errno)); 1.536 + _need_close = false; 1.537 + } 1.538 +} 1.539 + 1.540 +fileStream::fileStream(const char* file_name, const char* opentype) { 1.541 + _file = fopen(file_name, opentype); 1.542 + if (_file != NULL) { 1.543 + _need_close = true; 1.544 + } else { 1.545 + warning("Cannot open file %s due to %s\n", file_name, strerror(errno)); 1.546 + _need_close = false; 1.547 + } 1.548 +} 1.549 + 1.550 +void fileStream::write(const char* s, size_t len) { 1.551 + if (_file != NULL) { 1.552 + // Make an unused local variable to avoid warning from gcc 4.x compiler. 1.553 + size_t count = fwrite(s, 1, len, _file); 1.554 + } 1.555 + update_position(s, len); 1.556 +} 1.557 + 1.558 +long fileStream::fileSize() { 1.559 + long size = -1; 1.560 + if (_file != NULL) { 1.561 + long pos = ::ftell(_file); 1.562 + if (::fseek(_file, 0, SEEK_END) == 0) { 1.563 + size = ::ftell(_file); 1.564 + } 1.565 + ::fseek(_file, pos, SEEK_SET); 1.566 + } 1.567 + return size; 1.568 +} 1.569 + 1.570 +char* fileStream::readln(char *data, int count ) { 1.571 + char * ret = ::fgets(data, count, _file); 1.572 + //Get rid of annoying \n char 1.573 + data[::strlen(data)-1] = '\0'; 1.574 + return ret; 1.575 +} 1.576 + 1.577 +fileStream::~fileStream() { 1.578 + if (_file != NULL) { 1.579 + if (_need_close) fclose(_file); 1.580 + _file = NULL; 1.581 + } 1.582 +} 1.583 + 1.584 +void fileStream::flush() { 1.585 + fflush(_file); 1.586 +} 1.587 + 1.588 +fdStream::fdStream(const char* file_name) { 1.589 + _fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); 1.590 + _need_close = true; 1.591 +} 1.592 + 1.593 +fdStream::~fdStream() { 1.594 + if (_fd != -1) { 1.595 + if (_need_close) close(_fd); 1.596 + _fd = -1; 1.597 + } 1.598 +} 1.599 + 1.600 +void fdStream::write(const char* s, size_t len) { 1.601 + if (_fd != -1) { 1.602 + // Make an unused local variable to avoid warning from gcc 4.x compiler. 1.603 + size_t count = ::write(_fd, s, (int)len); 1.604 + } 1.605 + update_position(s, len); 1.606 +} 1.607 + 1.608 +// dump vm version, os version, platform info, build id, 1.609 +// memory usage and command line flags into header 1.610 +void gcLogFileStream::dump_loggc_header() { 1.611 + if (is_open()) { 1.612 + print_cr("%s", Abstract_VM_Version::internal_vm_info_string()); 1.613 + os::print_memory_info(this); 1.614 + print("CommandLine flags: "); 1.615 + CommandLineFlags::printSetFlags(this); 1.616 + } 1.617 +} 1.618 + 1.619 +gcLogFileStream::~gcLogFileStream() { 1.620 + if (_file != NULL) { 1.621 + if (_need_close) fclose(_file); 1.622 + _file = NULL; 1.623 + } 1.624 + if (_file_name != NULL) { 1.625 + FREE_C_HEAP_ARRAY(char, _file_name, mtInternal); 1.626 + _file_name = NULL; 1.627 + } 1.628 +} 1.629 + 1.630 +gcLogFileStream::gcLogFileStream(const char* file_name) { 1.631 + _cur_file_num = 0; 1.632 + _bytes_written = 0L; 1.633 + _file_name = make_log_name(file_name, NULL); 1.634 + 1.635 + // gc log file rotation 1.636 + if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) { 1.637 + char tempbuf[FILENAMEBUFLEN]; 1.638 + jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num); 1.639 + _file = fopen(tempbuf, "w"); 1.640 + } else { 1.641 + _file = fopen(_file_name, "w"); 1.642 + } 1.643 + if (_file != NULL) { 1.644 + _need_close = true; 1.645 + dump_loggc_header(); 1.646 + } else { 1.647 + warning("Cannot open file %s due to %s\n", _file_name, strerror(errno)); 1.648 + _need_close = false; 1.649 + } 1.650 +} 1.651 + 1.652 +void gcLogFileStream::write(const char* s, size_t len) { 1.653 + if (_file != NULL) { 1.654 + size_t count = fwrite(s, 1, len, _file); 1.655 + _bytes_written += count; 1.656 + } 1.657 + update_position(s, len); 1.658 +} 1.659 + 1.660 +// rotate_log must be called from VMThread at safepoint. In case need change parameters 1.661 +// for gc log rotation from thread other than VMThread, a sub type of VM_Operation 1.662 +// should be created and be submitted to VMThread's operation queue. DO NOT call this 1.663 +// function directly. Currently, it is safe to rotate log at safepoint through VMThread. 1.664 +// That is, no mutator threads and concurrent GC threads run parallel with VMThread to 1.665 +// write to gc log file at safepoint. If in future, changes made for mutator threads or 1.666 +// concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log 1.667 +// must be synchronized. 1.668 +void gcLogFileStream::rotate_log(bool force, outputStream* out) { 1.669 + char time_msg[FILENAMEBUFLEN]; 1.670 + char time_str[EXTRACHARLEN]; 1.671 + char current_file_name[FILENAMEBUFLEN]; 1.672 + char renamed_file_name[FILENAMEBUFLEN]; 1.673 + 1.674 + if (!should_rotate(force)) { 1.675 + return; 1.676 + } 1.677 + 1.678 +#ifdef ASSERT 1.679 + Thread *thread = Thread::current(); 1.680 + assert(thread == NULL || 1.681 + (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()), 1.682 + "Must be VMThread at safepoint"); 1.683 +#endif 1.684 + if (NumberOfGCLogFiles == 1) { 1.685 + // rotate in same file 1.686 + rewind(); 1.687 + _bytes_written = 0L; 1.688 + jio_snprintf(time_msg, sizeof(time_msg), "File %s rotated at %s\n", 1.689 + _file_name, os::local_time_string((char *)time_str, sizeof(time_str))); 1.690 + write(time_msg, strlen(time_msg)); 1.691 + 1.692 + if (out != NULL) { 1.693 + out->print("%s", time_msg); 1.694 + } 1.695 + 1.696 + dump_loggc_header(); 1.697 + return; 1.698 + } 1.699 + 1.700 +#if defined(_WINDOWS) 1.701 +#ifndef F_OK 1.702 +#define F_OK 0 1.703 +#endif 1.704 +#endif // _WINDOWS 1.705 + 1.706 + // rotate file in names extended_filename.0, extended_filename.1, ..., 1.707 + // extended_filename.<NumberOfGCLogFiles - 1>. Current rotation file name will 1.708 + // have a form of extended_filename.<i>.current where i is the current rotation 1.709 + // file number. After it reaches max file size, the file will be saved and renamed 1.710 + // with .current removed from its tail. 1.711 + size_t filename_len = strlen(_file_name); 1.712 + if (_file != NULL) { 1.713 + jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d", 1.714 + _file_name, _cur_file_num); 1.715 + jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX, 1.716 + _file_name, _cur_file_num); 1.717 + 1.718 + const char* msg = force ? "GC log rotation request has been received." 1.719 + : "GC log file has reached the maximum size."; 1.720 + jio_snprintf(time_msg, sizeof(time_msg), "%s %s Saved as %s\n", 1.721 + os::local_time_string((char *)time_str, sizeof(time_str)), 1.722 + msg, renamed_file_name); 1.723 + write(time_msg, strlen(time_msg)); 1.724 + 1.725 + if (out != NULL) { 1.726 + out->print("%s", time_msg); 1.727 + } 1.728 + 1.729 + fclose(_file); 1.730 + _file = NULL; 1.731 + 1.732 + bool can_rename = true; 1.733 + if (access(current_file_name, F_OK) != 0) { 1.734 + // current file does not exist? 1.735 + warning("No source file exists, cannot rename\n"); 1.736 + can_rename = false; 1.737 + } 1.738 + if (can_rename) { 1.739 + if (access(renamed_file_name, F_OK) == 0) { 1.740 + if (remove(renamed_file_name) != 0) { 1.741 + warning("Could not delete existing file %s\n", renamed_file_name); 1.742 + can_rename = false; 1.743 + } 1.744 + } else { 1.745 + // file does not exist, ok to rename 1.746 + } 1.747 + } 1.748 + if (can_rename && rename(current_file_name, renamed_file_name) != 0) { 1.749 + warning("Could not rename %s to %s\n", _file_name, renamed_file_name); 1.750 + } 1.751 + } 1.752 + 1.753 + _cur_file_num++; 1.754 + if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0; 1.755 + jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX, 1.756 + _file_name, _cur_file_num); 1.757 + _file = fopen(current_file_name, "w"); 1.758 + 1.759 + if (_file != NULL) { 1.760 + _bytes_written = 0L; 1.761 + _need_close = true; 1.762 + // reuse current_file_name for time_msg 1.763 + jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, 1.764 + "%s.%d", _file_name, _cur_file_num); 1.765 + jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n", 1.766 + os::local_time_string((char *)time_str, sizeof(time_str)), 1.767 + current_file_name); 1.768 + write(time_msg, strlen(time_msg)); 1.769 + 1.770 + if (out != NULL) { 1.771 + out->print("%s", time_msg); 1.772 + } 1.773 + 1.774 + dump_loggc_header(); 1.775 + // remove the existing file 1.776 + if (access(current_file_name, F_OK) == 0) { 1.777 + if (remove(current_file_name) != 0) { 1.778 + warning("Could not delete existing file %s\n", current_file_name); 1.779 + } 1.780 + } 1.781 + } else { 1.782 + warning("failed to open rotation log file %s due to %s\n" 1.783 + "Turned off GC log file rotation\n", 1.784 + _file_name, strerror(errno)); 1.785 + _need_close = false; 1.786 + FLAG_SET_DEFAULT(UseGCLogFileRotation, false); 1.787 + } 1.788 +} 1.789 + 1.790 +defaultStream* defaultStream::instance = NULL; 1.791 +int defaultStream::_output_fd = 1; 1.792 +int defaultStream::_error_fd = 2; 1.793 +FILE* defaultStream::_output_stream = stdout; 1.794 +FILE* defaultStream::_error_stream = stderr; 1.795 + 1.796 +#define LOG_MAJOR_VERSION 160 1.797 +#define LOG_MINOR_VERSION 1 1.798 + 1.799 +void defaultStream::init() { 1.800 + _inited = true; 1.801 + if (LogVMOutput || LogCompilation) { 1.802 + init_log(); 1.803 + } 1.804 +} 1.805 + 1.806 +bool defaultStream::has_log_file() { 1.807 + // lazily create log file (at startup, LogVMOutput is false even 1.808 + // if +LogVMOutput is used, because the flags haven't been parsed yet) 1.809 + // For safer printing during fatal error handling, do not init logfile 1.810 + // if a VM error has been reported. 1.811 + if (!_inited && !is_error_reported()) init(); 1.812 + return _log_file != NULL; 1.813 +} 1.814 + 1.815 +void defaultStream::init_log() { 1.816 + // %%% Need a MutexLocker? 1.817 + const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log"; 1.818 + const char* try_name = make_log_name(log_name, NULL); 1.819 + fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); 1.820 + if (!file->is_open()) { 1.821 + // Try again to open the file. 1.822 + char warnbuf[O_BUFLEN*2]; 1.823 + jio_snprintf(warnbuf, sizeof(warnbuf), 1.824 + "Warning: Cannot open log file: %s\n", try_name); 1.825 + // Note: This feature is for maintainer use only. No need for L10N. 1.826 + jio_print(warnbuf); 1.827 + FREE_C_HEAP_ARRAY(char, try_name, mtInternal); 1.828 + try_name = make_log_name(log_name, os::get_temp_directory()); 1.829 + jio_snprintf(warnbuf, sizeof(warnbuf), 1.830 + "Warning: Forcing option -XX:LogFile=%s\n", try_name); 1.831 + jio_print(warnbuf); 1.832 + delete file; 1.833 + file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); 1.834 + } 1.835 + FREE_C_HEAP_ARRAY(char, try_name, mtInternal); 1.836 + 1.837 + if (file->is_open()) { 1.838 + _log_file = file; 1.839 + xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file); 1.840 + _outer_xmlStream = xs; 1.841 + if (this == tty) xtty = xs; 1.842 + // Write XML header. 1.843 + xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>"); 1.844 + // (For now, don't bother to issue a DTD for this private format.) 1.845 + jlong time_ms = os::javaTimeMillis() - tty->time_stamp().milliseconds(); 1.846 + // %%% Should be: jlong time_ms = os::start_time_milliseconds(), if 1.847 + // we ever get round to introduce that method on the os class 1.848 + xs->head("hotspot_log version='%d %d'" 1.849 + " process='%d' time_ms='"INT64_FORMAT"'", 1.850 + LOG_MAJOR_VERSION, LOG_MINOR_VERSION, 1.851 + os::current_process_id(), (int64_t)time_ms); 1.852 + // Write VM version header immediately. 1.853 + xs->head("vm_version"); 1.854 + xs->head("name"); xs->text("%s", VM_Version::vm_name()); xs->cr(); 1.855 + xs->tail("name"); 1.856 + xs->head("release"); xs->text("%s", VM_Version::vm_release()); xs->cr(); 1.857 + xs->tail("release"); 1.858 + xs->head("info"); xs->text("%s", VM_Version::internal_vm_info_string()); xs->cr(); 1.859 + xs->tail("info"); 1.860 + xs->tail("vm_version"); 1.861 + // Record information about the command-line invocation. 1.862 + xs->head("vm_arguments"); // Cf. Arguments::print_on() 1.863 + if (Arguments::num_jvm_flags() > 0) { 1.864 + xs->head("flags"); 1.865 + Arguments::print_jvm_flags_on(xs->text()); 1.866 + xs->tail("flags"); 1.867 + } 1.868 + if (Arguments::num_jvm_args() > 0) { 1.869 + xs->head("args"); 1.870 + Arguments::print_jvm_args_on(xs->text()); 1.871 + xs->tail("args"); 1.872 + } 1.873 + if (Arguments::java_command() != NULL) { 1.874 + xs->head("command"); xs->text()->print_cr("%s", Arguments::java_command()); 1.875 + xs->tail("command"); 1.876 + } 1.877 + if (Arguments::sun_java_launcher() != NULL) { 1.878 + xs->head("launcher"); xs->text()->print_cr("%s", Arguments::sun_java_launcher()); 1.879 + xs->tail("launcher"); 1.880 + } 1.881 + if (Arguments::system_properties() != NULL) { 1.882 + xs->head("properties"); 1.883 + // Print it as a java-style property list. 1.884 + // System properties don't generally contain newlines, so don't bother with unparsing. 1.885 + for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { 1.886 + xs->text()->print_cr("%s=%s", p->key(), p->value()); 1.887 + } 1.888 + xs->tail("properties"); 1.889 + } 1.890 + xs->tail("vm_arguments"); 1.891 + // tty output per se is grouped under the <tty>...</tty> element. 1.892 + xs->head("tty"); 1.893 + // All further non-markup text gets copied to the tty: 1.894 + xs->_text = this; // requires friend declaration! 1.895 + } else { 1.896 + delete(file); 1.897 + // and leave xtty as NULL 1.898 + LogVMOutput = false; 1.899 + DisplayVMOutput = true; 1.900 + LogCompilation = false; 1.901 + } 1.902 +} 1.903 + 1.904 +// finish_log() is called during normal VM shutdown. finish_log_on_error() is 1.905 +// called by ostream_abort() after a fatal error. 1.906 +// 1.907 +void defaultStream::finish_log() { 1.908 + xmlStream* xs = _outer_xmlStream; 1.909 + xs->done("tty"); 1.910 + 1.911 + // Other log forks are appended here, at the End of Time: 1.912 + CompileLog::finish_log(xs->out()); // write compile logging, if any, now 1.913 + 1.914 + xs->done("hotspot_log"); 1.915 + xs->flush(); 1.916 + 1.917 + fileStream* file = _log_file; 1.918 + _log_file = NULL; 1.919 + 1.920 + delete _outer_xmlStream; 1.921 + _outer_xmlStream = NULL; 1.922 + 1.923 + file->flush(); 1.924 + delete file; 1.925 +} 1.926 + 1.927 +void defaultStream::finish_log_on_error(char *buf, int buflen) { 1.928 + xmlStream* xs = _outer_xmlStream; 1.929 + 1.930 + if (xs && xs->out()) { 1.931 + 1.932 + xs->done_raw("tty"); 1.933 + 1.934 + // Other log forks are appended here, at the End of Time: 1.935 + CompileLog::finish_log_on_error(xs->out(), buf, buflen); // write compile logging, if any, now 1.936 + 1.937 + xs->done_raw("hotspot_log"); 1.938 + xs->flush(); 1.939 + 1.940 + fileStream* file = _log_file; 1.941 + _log_file = NULL; 1.942 + _outer_xmlStream = NULL; 1.943 + 1.944 + if (file) { 1.945 + file->flush(); 1.946 + 1.947 + // Can't delete or close the file because delete and fclose aren't 1.948 + // async-safe. We are about to die, so leave it to the kernel. 1.949 + // delete file; 1.950 + } 1.951 + } 1.952 +} 1.953 + 1.954 +intx defaultStream::hold(intx writer_id) { 1.955 + bool has_log = has_log_file(); // check before locking 1.956 + if (// impossible, but who knows? 1.957 + writer_id == NO_WRITER || 1.958 + 1.959 + // bootstrap problem 1.960 + tty_lock == NULL || 1.961 + 1.962 + // can't grab a lock or call Thread::current() if TLS isn't initialized 1.963 + ThreadLocalStorage::thread() == NULL || 1.964 + 1.965 + // developer hook 1.966 + !SerializeVMOutput || 1.967 + 1.968 + // VM already unhealthy 1.969 + is_error_reported() || 1.970 + 1.971 + // safepoint == global lock (for VM only) 1.972 + (SafepointSynchronize::is_synchronizing() && 1.973 + Thread::current()->is_VM_thread()) 1.974 + ) { 1.975 + // do not attempt to lock unless we know the thread and the VM is healthy 1.976 + return NO_WRITER; 1.977 + } 1.978 + if (_writer == writer_id) { 1.979 + // already held, no need to re-grab the lock 1.980 + return NO_WRITER; 1.981 + } 1.982 + tty_lock->lock_without_safepoint_check(); 1.983 + // got the lock 1.984 + if (writer_id != _last_writer) { 1.985 + if (has_log) { 1.986 + _log_file->bol(); 1.987 + // output a hint where this output is coming from: 1.988 + _log_file->print_cr("<writer thread='" UINTX_FORMAT "'/>", writer_id); 1.989 + } 1.990 + _last_writer = writer_id; 1.991 + } 1.992 + _writer = writer_id; 1.993 + return writer_id; 1.994 +} 1.995 + 1.996 +void defaultStream::release(intx holder) { 1.997 + if (holder == NO_WRITER) { 1.998 + // nothing to release: either a recursive lock, or we scribbled (too bad) 1.999 + return; 1.1000 + } 1.1001 + if (_writer != holder) { 1.1002 + return; // already unlocked, perhaps via break_tty_lock_for_safepoint 1.1003 + } 1.1004 + _writer = NO_WRITER; 1.1005 + tty_lock->unlock(); 1.1006 +} 1.1007 + 1.1008 + 1.1009 +// Yuck: jio_print does not accept char*/len. 1.1010 +static void call_jio_print(const char* s, size_t len) { 1.1011 + char buffer[O_BUFLEN+100]; 1.1012 + if (len > sizeof(buffer)-1) { 1.1013 + warning("increase O_BUFLEN in ostream.cpp -- output truncated"); 1.1014 + len = sizeof(buffer)-1; 1.1015 + } 1.1016 + strncpy(buffer, s, len); 1.1017 + buffer[len] = '\0'; 1.1018 + jio_print(buffer); 1.1019 +} 1.1020 + 1.1021 + 1.1022 +void defaultStream::write(const char* s, size_t len) { 1.1023 + intx thread_id = os::current_thread_id(); 1.1024 + intx holder = hold(thread_id); 1.1025 + 1.1026 + if (DisplayVMOutput && 1.1027 + (_outer_xmlStream == NULL || !_outer_xmlStream->inside_attrs())) { 1.1028 + // print to output stream. It can be redirected by a vfprintf hook 1.1029 + if (s[len] == '\0') { 1.1030 + jio_print(s); 1.1031 + } else { 1.1032 + call_jio_print(s, len); 1.1033 + } 1.1034 + } 1.1035 + 1.1036 + // print to log file 1.1037 + if (has_log_file()) { 1.1038 + int nl0 = _newlines; 1.1039 + xmlTextStream::write(s, len); 1.1040 + // flush the log file too, if there were any newlines 1.1041 + if (nl0 != _newlines){ 1.1042 + flush(); 1.1043 + } 1.1044 + } else { 1.1045 + update_position(s, len); 1.1046 + } 1.1047 + 1.1048 + release(holder); 1.1049 +} 1.1050 + 1.1051 +intx ttyLocker::hold_tty() { 1.1052 + if (defaultStream::instance == NULL) return defaultStream::NO_WRITER; 1.1053 + intx thread_id = os::current_thread_id(); 1.1054 + return defaultStream::instance->hold(thread_id); 1.1055 +} 1.1056 + 1.1057 +void ttyLocker::release_tty(intx holder) { 1.1058 + if (holder == defaultStream::NO_WRITER) return; 1.1059 + defaultStream::instance->release(holder); 1.1060 +} 1.1061 + 1.1062 +bool ttyLocker::release_tty_if_locked() { 1.1063 + intx thread_id = os::current_thread_id(); 1.1064 + if (defaultStream::instance->writer() == thread_id) { 1.1065 + // release the lock and return true so callers know if was 1.1066 + // previously held. 1.1067 + release_tty(thread_id); 1.1068 + return true; 1.1069 + } 1.1070 + return false; 1.1071 +} 1.1072 + 1.1073 +void ttyLocker::break_tty_lock_for_safepoint(intx holder) { 1.1074 + if (defaultStream::instance != NULL && 1.1075 + defaultStream::instance->writer() == holder) { 1.1076 + if (xtty != NULL) { 1.1077 + xtty->print_cr("<!-- safepoint while printing -->"); 1.1078 + } 1.1079 + defaultStream::instance->release(holder); 1.1080 + } 1.1081 + // (else there was no lock to break) 1.1082 +} 1.1083 + 1.1084 +void ostream_init() { 1.1085 + if (defaultStream::instance == NULL) { 1.1086 + defaultStream::instance = new(ResourceObj::C_HEAP, mtInternal) defaultStream(); 1.1087 + tty = defaultStream::instance; 1.1088 + 1.1089 + // We want to ensure that time stamps in GC logs consider time 0 1.1090 + // the time when the JVM is initialized, not the first time we ask 1.1091 + // for a time stamp. So, here, we explicitly update the time stamp 1.1092 + // of tty. 1.1093 + tty->time_stamp().update_to(1); 1.1094 + } 1.1095 +} 1.1096 + 1.1097 +void ostream_init_log() { 1.1098 + // For -Xloggc:<file> option - called in runtime/thread.cpp 1.1099 + // Note : this must be called AFTER ostream_init() 1.1100 + 1.1101 + gclog_or_tty = tty; // default to tty 1.1102 + if (Arguments::gc_log_filename() != NULL) { 1.1103 + fileStream * gclog = new(ResourceObj::C_HEAP, mtInternal) 1.1104 + gcLogFileStream(Arguments::gc_log_filename()); 1.1105 + if (gclog->is_open()) { 1.1106 + // now we update the time stamp of the GC log to be synced up 1.1107 + // with tty. 1.1108 + gclog->time_stamp().update_to(tty->time_stamp().ticks()); 1.1109 + } 1.1110 + gclog_or_tty = gclog; 1.1111 + } 1.1112 + 1.1113 + // If we haven't lazily initialized the logfile yet, do it now, 1.1114 + // to avoid the possibility of lazy initialization during a VM 1.1115 + // crash, which can affect the stability of the fatal error handler. 1.1116 + defaultStream::instance->has_log_file(); 1.1117 +} 1.1118 + 1.1119 +// ostream_exit() is called during normal VM exit to finish log files, flush 1.1120 +// output and free resource. 1.1121 +void ostream_exit() { 1.1122 + static bool ostream_exit_called = false; 1.1123 + if (ostream_exit_called) return; 1.1124 + ostream_exit_called = true; 1.1125 + if (gclog_or_tty != tty) { 1.1126 + delete gclog_or_tty; 1.1127 + } 1.1128 + { 1.1129 + // we temporaly disable PrintMallocFree here 1.1130 + // as otherwise it'll lead to using of almost deleted 1.1131 + // tty or defaultStream::instance in logging facility 1.1132 + // of HeapFree(), see 6391258 1.1133 + DEBUG_ONLY(FlagSetting fs(PrintMallocFree, false);) 1.1134 + if (tty != defaultStream::instance) { 1.1135 + delete tty; 1.1136 + } 1.1137 + if (defaultStream::instance != NULL) { 1.1138 + delete defaultStream::instance; 1.1139 + } 1.1140 + } 1.1141 + tty = NULL; 1.1142 + xtty = NULL; 1.1143 + gclog_or_tty = NULL; 1.1144 + defaultStream::instance = NULL; 1.1145 +} 1.1146 + 1.1147 +// ostream_abort() is called by os::abort() when VM is about to die. 1.1148 +void ostream_abort() { 1.1149 + // Here we can't delete gclog_or_tty and tty, just flush their output 1.1150 + if (gclog_or_tty) gclog_or_tty->flush(); 1.1151 + if (tty) tty->flush(); 1.1152 + 1.1153 + if (defaultStream::instance != NULL) { 1.1154 + static char buf[4096]; 1.1155 + defaultStream::instance->finish_log_on_error(buf, sizeof(buf)); 1.1156 + } 1.1157 +} 1.1158 + 1.1159 +staticBufferStream::staticBufferStream(char* buffer, size_t buflen, 1.1160 + outputStream *outer_stream) { 1.1161 + _buffer = buffer; 1.1162 + _buflen = buflen; 1.1163 + _outer_stream = outer_stream; 1.1164 + // compile task prints time stamp relative to VM start 1.1165 + _stamp.update_to(1); 1.1166 +} 1.1167 + 1.1168 +void staticBufferStream::write(const char* c, size_t len) { 1.1169 + _outer_stream->print_raw(c, (int)len); 1.1170 +} 1.1171 + 1.1172 +void staticBufferStream::flush() { 1.1173 + _outer_stream->flush(); 1.1174 +} 1.1175 + 1.1176 +void staticBufferStream::print(const char* format, ...) { 1.1177 + va_list ap; 1.1178 + va_start(ap, format); 1.1179 + size_t len; 1.1180 + const char* str = do_vsnprintf(_buffer, _buflen, format, ap, false, len); 1.1181 + write(str, len); 1.1182 + va_end(ap); 1.1183 +} 1.1184 + 1.1185 +void staticBufferStream::print_cr(const char* format, ...) { 1.1186 + va_list ap; 1.1187 + va_start(ap, format); 1.1188 + size_t len; 1.1189 + const char* str = do_vsnprintf(_buffer, _buflen, format, ap, true, len); 1.1190 + write(str, len); 1.1191 + va_end(ap); 1.1192 +} 1.1193 + 1.1194 +void staticBufferStream::vprint(const char *format, va_list argptr) { 1.1195 + size_t len; 1.1196 + const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, false, len); 1.1197 + write(str, len); 1.1198 +} 1.1199 + 1.1200 +void staticBufferStream::vprint_cr(const char* format, va_list argptr) { 1.1201 + size_t len; 1.1202 + const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, true, len); 1.1203 + write(str, len); 1.1204 +} 1.1205 + 1.1206 +bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStream() { 1.1207 + buffer_length = initial_size; 1.1208 + buffer = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); 1.1209 + buffer_pos = 0; 1.1210 + buffer_fixed = false; 1.1211 + buffer_max = bufmax; 1.1212 +} 1.1213 + 1.1214 +bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax) : outputStream() { 1.1215 + buffer_length = fixed_buffer_size; 1.1216 + buffer = fixed_buffer; 1.1217 + buffer_pos = 0; 1.1218 + buffer_fixed = true; 1.1219 + buffer_max = bufmax; 1.1220 +} 1.1221 + 1.1222 +void bufferedStream::write(const char* s, size_t len) { 1.1223 + 1.1224 + if(buffer_pos + len > buffer_max) { 1.1225 + flush(); 1.1226 + } 1.1227 + 1.1228 + size_t end = buffer_pos + len; 1.1229 + if (end >= buffer_length) { 1.1230 + if (buffer_fixed) { 1.1231 + // if buffer cannot resize, silently truncate 1.1232 + len = buffer_length - buffer_pos - 1; 1.1233 + } else { 1.1234 + // For small overruns, double the buffer. For larger ones, 1.1235 + // increase to the requested size. 1.1236 + if (end < buffer_length * 2) { 1.1237 + end = buffer_length * 2; 1.1238 + } 1.1239 + buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end, mtInternal); 1.1240 + buffer_length = end; 1.1241 + } 1.1242 + } 1.1243 + memcpy(buffer + buffer_pos, s, len); 1.1244 + buffer_pos += len; 1.1245 + update_position(s, len); 1.1246 +} 1.1247 + 1.1248 +char* bufferedStream::as_string() { 1.1249 + char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1); 1.1250 + strncpy(copy, buffer, buffer_pos); 1.1251 + copy[buffer_pos] = 0; // terminating null 1.1252 + return copy; 1.1253 +} 1.1254 + 1.1255 +bufferedStream::~bufferedStream() { 1.1256 + if (!buffer_fixed) { 1.1257 + FREE_C_HEAP_ARRAY(char, buffer, mtInternal); 1.1258 + } 1.1259 +} 1.1260 + 1.1261 +#ifndef PRODUCT 1.1262 + 1.1263 +#if defined(SOLARIS) || defined(LINUX) || defined(AIX) || defined(_ALLBSD_SOURCE) 1.1264 +#include <sys/types.h> 1.1265 +#include <sys/socket.h> 1.1266 +#include <netinet/in.h> 1.1267 +#include <arpa/inet.h> 1.1268 +#endif 1.1269 + 1.1270 +// Network access 1.1271 +networkStream::networkStream() : bufferedStream(1024*10, 1024*10) { 1.1272 + 1.1273 + _socket = -1; 1.1274 + 1.1275 + int result = os::socket(AF_INET, SOCK_STREAM, 0); 1.1276 + if (result <= 0) { 1.1277 + assert(false, "Socket could not be created!"); 1.1278 + } else { 1.1279 + _socket = result; 1.1280 + } 1.1281 +} 1.1282 + 1.1283 +int networkStream::read(char *buf, size_t len) { 1.1284 + return os::recv(_socket, buf, (int)len, 0); 1.1285 +} 1.1286 + 1.1287 +void networkStream::flush() { 1.1288 + if (size() != 0) { 1.1289 + int result = os::raw_send(_socket, (char *)base(), size(), 0); 1.1290 + assert(result != -1, "connection error"); 1.1291 + assert(result == (int)size(), "didn't send enough data"); 1.1292 + } 1.1293 + reset(); 1.1294 +} 1.1295 + 1.1296 +networkStream::~networkStream() { 1.1297 + close(); 1.1298 +} 1.1299 + 1.1300 +void networkStream::close() { 1.1301 + if (_socket != -1) { 1.1302 + flush(); 1.1303 + os::socket_close(_socket); 1.1304 + _socket = -1; 1.1305 + } 1.1306 +} 1.1307 + 1.1308 +bool networkStream::connect(const char *ip, short port) { 1.1309 + 1.1310 + struct sockaddr_in server; 1.1311 + server.sin_family = AF_INET; 1.1312 + server.sin_port = htons(port); 1.1313 + 1.1314 + server.sin_addr.s_addr = inet_addr(ip); 1.1315 + if (server.sin_addr.s_addr == (uint32_t)-1) { 1.1316 + struct hostent* host = os::get_host_by_name((char*)ip); 1.1317 + if (host != NULL) { 1.1318 + memcpy(&server.sin_addr, host->h_addr_list[0], host->h_length); 1.1319 + } else { 1.1320 + return false; 1.1321 + } 1.1322 + } 1.1323 + 1.1324 + 1.1325 + int result = os::connect(_socket, (struct sockaddr*)&server, sizeof(struct sockaddr_in)); 1.1326 + return (result >= 0); 1.1327 +} 1.1328 + 1.1329 +#endif