--- old/src/share/vm/runtime/arguments.cpp Thu Aug 15 09:00:50 2013 +++ new/src/share/vm/runtime/arguments.cpp Thu Aug 15 09:00:50 2013 @@ -1844,7 +1844,7 @@ (NumberOfGCLogFiles == 0) || (GCLogFileSize == 0)) { jio_fprintf(defaultStream::output_stream(), - "To enable GC log rotation, use -Xloggc: -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles= -XX:GCLogFileSize=\n" + "To enable GC log rotation, use -Xloggc: -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles= -XX:GCLogFileSize=[k|K|m|M]\n" "where num_of_file > 0 and num_of_size > 0\n" "GC log rotation is turned off\n"); UseGCLogFileRotation = false; --- old/src/share/vm/utilities/ostream.cpp Thu Aug 15 09:00:51 2013 +++ new/src/share/vm/utilities/ostream.cpp Thu Aug 15 09:00:51 2013 @@ -423,6 +423,7 @@ update_position(s, len); } +#define EXTRACHARLEN 20 rotatingFileStream::~rotatingFileStream() { if (_file != NULL) { if (_need_close) fclose(_file); @@ -435,8 +436,12 @@ rotatingFileStream::rotatingFileStream(const char* file_name) { _cur_file_num = 0; _bytes_written = 0L; - _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); - jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); + _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name) + EXTRACHARLEN, mtInternal); + if (NumberOfGCLogFiles == 1) { + jio_snprintf(_file_name, strlen(file_name) + EXTRACHARLEN, "%s", file_name); + } else { + jio_snprintf(_file_name, strlen(file_name) + EXTRACHARLEN, "%s.%d.current", file_name, _cur_file_num); + } _file = fopen(_file_name, "w"); _need_close = true; } @@ -444,8 +449,12 @@ rotatingFileStream::rotatingFileStream(const char* file_name, const char* opentype) { _cur_file_num = 0; _bytes_written = 0L; - _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); - jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); + _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name) + EXTRACHARLEN, mtInternal); + if (NumberOfGCLogFiles == 1) { + jio_snprintf(_file_name, strlen(file_name) + EXTRACHARLEN, "%s", file_name); + } else { + jio_snprintf(_file_name, strlen(file_name) + EXTRACHARLEN, "%s.%d.current", file_name, _cur_file_num); + } _file = fopen(_file_name, opentype); _need_close = true; } @@ -467,6 +476,10 @@ // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log // must be synchronized. void rotatingFileStream::rotate_log() { + char time_msg[256]; + char time_str[64]; + char renamed_file_name[256]; + if (_bytes_written < (jlong)GCLogFileSize) { return; } @@ -484,20 +497,54 @@ return; } - // rotate file in names file.0, file.1, file.2, ..., file. - // close current file, rotate to next file + // rotate file in names file.0, file.1, ..., file. + // current file name is like file.n.current, after reaches to maximum size, + // will be renamed to file.n + size_t filename_len = strlen(Arguments::gc_log_filename()); if (_file != NULL) { - _cur_file_num ++; - if (_cur_file_num >= NumberOfGCLogFiles) _cur_file_num = 0; - jio_snprintf(_file_name, strlen(Arguments::gc_log_filename()) + 10, "%s.%d", + jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d", Arguments::gc_log_filename(), _cur_file_num); + jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file has reached the" + " maximum size. Saved as %s\n", + os::local_time_string((char *)time_str, sizeof(time_str)), + renamed_file_name); + this->write(time_msg, strlen(time_msg)); fclose(_file); _file = NULL; + + bool can_rename = true; + if (access(renamed_file_name, NOT_WINDOWS(F_OK) WINDOWS_ONLY(0)) == 0) { + if (remove(renamed_file_name) != 0) { + warning("Could not remove existed file %s\n", renamed_file_name); + can_rename = false; + } + } + if (can_rename && rename(_file_name, renamed_file_name) != 0) { + warning("Could not rename %s to %s\n", _file_name, renamed_file_name); + } + // current file name + _cur_file_num++; + if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0; + jio_snprintf(_file_name, filename_len + EXTRACHARLEN, "%s.%d.current", + Arguments::gc_log_filename(), _cur_file_num); } _file = fopen(_file_name, "w"); if (_file != NULL) { _bytes_written = 0L; _need_close = true; + // reuse renamed_file_name for time_msg + jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, + "%s.%d", Arguments::gc_log_filename(), _cur_file_num); + jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n", + os::local_time_string((char *)time_str, sizeof(time_str)), + renamed_file_name); + this->write(time_msg, strlen(time_msg)); + // remove the existed file + if (access(renamed_file_name, NOT_WINDOWS(F_OK) WINDOWS_ONLY(0)) == 0) { + if (remove(renamed_file_name) != 0) { + warning("Could not remove existed file %s\n", renamed_file_name); + } + } } else { tty->print_cr("failed to open rotation log file %s due to %s\n", _file_name, strerror(errno));