6941923: RFE: Handling large log files produced by long running Java Applications
Yasumasa Suenaga
suenaga.yasumasa at oss.ntt.co.jp
Mon Sep 12 01:18:36 UTC 2011
Hi,
I'm using "logrotate" tool on RHEL for various log rotation.
Now, HotSpot has gclog rotation function for log size base.
However, I need to rotate gc log synchronizing with logrotate tool.
So, I've made a patch for executing gclog rotation from external tool.
* Changes in HotSpot (hotspot.patch):
* gclog rotation request is received via AttachListener.
* logrotation function ( rotatingFileStream::rotate_log() ) has
1 parameter. It's determined that gclog rotation is forced or not.
* HotSpot allows "GCLogFileSize == 0" . Because we can rotate gclog
via external tool.
* Changes in JDK (jdk.patch):
* gclog rotation is invoked via "jinfo" command with "-rotategclog"
option.
* With "-rotategclog -force" option, gclog is rotated mandatorily.
* "jinfo" is executed "rotategclog" command in AttachListener on
target JVM.
I've attached these patch in this email. Please check it.
I would like to contribute this patch, and I hope to apply this patch to
JDK 6 / 7 / 8.
Please cooperate.
Best regards,
Yasumasa
-------------- next part --------------
diff -r fc569517f3cf src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
--- a/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java Mon Sep 05 23:58:19 2011 -0700
+++ b/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java Fri Sep 09 14:45:26 2011 +0900
@@ -195,6 +195,12 @@
return executeCommand("printflag", name);
}
+ // invoke gclog rotation
+ public InputStream rotateGCLog(String option) throws IOException {
+ return executeCommand("rotategclog", option);
+
+ }
+
// -- Supporting methods
diff -r fc569517f3cf src/share/classes/sun/tools/jinfo/JInfo.java
--- a/src/share/classes/sun/tools/jinfo/JInfo.java Mon Sep 05 23:58:19 2011 -0700
+++ b/src/share/classes/sun/tools/jinfo/JInfo.java Fri Sep 09 14:45:26 2011 +0900
@@ -58,7 +58,7 @@
if (args.length != 2 && args.length != 3) {
usage();
}
- } else if (arg1.equals("-flag")) {
+ } else if (arg1.equals("-flag") || arg1.equals("-rotategclog")) {
// do not use SA, use attach-on-demand
useSA = false;
} else {
@@ -70,10 +70,15 @@
if (useSA) {
runTool(args);
} else {
- if (args.length == 3) {
+ if (arg1.equals("-flag")) {
String pid = args[2];
String option = args[1];
flag(pid, option);
+ } else if (arg1.equals("-rotategclog")) {
+ if(args.length == 2) // no option
+ rotategclog(args[1], null);
+ else // "-force" option
+ rotategclog(args[2], args[1]);
} else {
usage();
}
@@ -142,6 +147,15 @@
drain(vm, in);
}
+ private static void rotategclog(String pid, String option) throws IOException {
+ VirtualMachine vm = attach(pid);
+ InputStream in;
+
+ in = ((HotSpotVirtualMachine)vm).rotateGCLog(option);
+
+ drain(vm, in);
+ }
+
// Attach to <pid>, exiting if we fail to attach
private static VirtualMachine attach(String pid) {
try {
@@ -195,6 +209,7 @@
System.out.println(" -flag [+|-]<name> to enable or disable the named VM flag");
System.out.println(" -flag <name>=<value> to set the named VM flag to the given value");
System.out.println(" -flags to print VM flags");
+ System.out.println(" -rotategclog [-force] to rotate gclog");
System.out.println(" -sysprops to print Java system properties");
System.out.println(" <no option> to print both of the above");
System.out.println(" -h | -help to print this help message");
@@ -206,6 +221,7 @@
System.out.println(" -flag <name> to print the value of the named VM flag");
System.out.println(" -flag [+|-]<name> to enable or disable the named VM flag");
System.out.println(" -flag <name>=<value> to set the named VM flag to the given value");
+ System.out.println(" -rotategclog [-force] to rotate gclog");
System.out.println(" -h | -help to print this help message");
}
-------------- next part --------------
diff -r 0fa3ace511fe src/share/vm/runtime/arguments.cpp
--- a/src/share/vm/runtime/arguments.cpp Thu Sep 01 13:54:24 2011 -0700
+++ b/src/share/vm/runtime/arguments.cpp Fri Sep 09 15:45:32 2011 +0900
@@ -1682,18 +1682,16 @@
// NumberOfGCLogFiles is 0, or GCLogFileSize is 0
void check_gclog_consistency() {
if (UseGCLogFileRotation) {
- if ((Arguments::gc_log_filename() == NULL) ||
- (NumberOfGCLogFiles == 0) ||
- (GCLogFileSize == 0)) {
+ if ((Arguments::gc_log_filename() == NULL) || (NumberOfGCLogFiles == 0)){
jio_fprintf(defaultStream::output_stream(),
"To enable GC log rotation, use -Xloggc:<filename> -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=<num_of_files> -XX:GCLogFileSize=<num_of_size>\n"
- "where num_of_file > 0 and num_of_size > 0\n"
+ "where num_of_file > 0\n"
"GC log rotation is turned off\n");
UseGCLogFileRotation = false;
}
}
- if (UseGCLogFileRotation && GCLogFileSize < 8*K) {
+ if (UseGCLogFileRotation && !FLAG_IS_DEFAULT(GCLogFileSize) && (GCLogFileSize < 8*K)) {
FLAG_SET_CMDLINE(uintx, GCLogFileSize, 8*K);
jio_fprintf(defaultStream::output_stream(),
"GCLogFileSize changed to minimum 8K\n");
diff -r 0fa3ace511fe src/share/vm/runtime/safepoint.cpp
--- a/src/share/vm/runtime/safepoint.cpp Thu Sep 01 13:54:24 2011 -0700
+++ b/src/share/vm/runtime/safepoint.cpp Fri Sep 09 15:45:32 2011 +0900
@@ -514,7 +514,7 @@
// rotate log files?
if (UseGCLogFileRotation) {
- gclog_or_tty->rotate_log();
+ gclog_or_tty->rotate_log(false);
}
}
diff -r 0fa3ace511fe src/share/vm/runtime/vm_operations.hpp
--- a/src/share/vm/runtime/vm_operations.hpp Thu Sep 01 13:54:24 2011 -0700
+++ b/src/share/vm/runtime/vm_operations.hpp Fri Sep 09 15:45:32 2011 +0900
@@ -94,6 +94,7 @@
template(HeapIterateOperation) \
template(ReportJavaOutOfMemory) \
template(Exit) \
+ template(RotateGCLog) \
class VM_Operation: public CHeapObj {
public:
@@ -405,4 +406,17 @@
void doit();
};
+
+class VM_RotateGCLog: public VM_Operation {
+
+ private:
+ bool _isForce;
+
+ public:
+ VM_RotateGCLog(bool isForce) { _isForce = isForce; }
+ VMOp_Type type() const { return VMOp_RotateGCLog; }
+ void doit() { gclog_or_tty->rotate_log(_isForce); }
+
+};
+
#endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP
diff -r 0fa3ace511fe src/share/vm/services/attachListener.cpp
--- a/src/share/vm/services/attachListener.cpp Thu Sep 01 13:54:24 2011 -0700
+++ b/src/share/vm/services/attachListener.cpp Fri Sep 09 15:45:32 2011 +0900
@@ -351,6 +351,35 @@
return JNI_OK;
}
+// Implementation of "rotategclog" command
+//
+// Input arguments :-
+// arg0: "-force"
+static jint rotate_gclog(AttachOperation* op, outputStream* out) {
+ const char* arg0 = op->arg(0);
+ bool isForce = false;
+
+ if(arg0 != NULL){
+ if(strcmp(arg0, "-force") == 0){
+ isForce = true;
+ }
+ else if(arg0[0] != '\0'){
+ out->print_cr("Unknown option: %s", arg0);
+ return JNI_ERR;
+ }
+ }
+
+ if(!UseGCLogFileRotation){
+ out->print_cr("Target VM is not supported gclog file rotation.");
+ return JNI_ERR;
+ }
+
+ VM_RotateGCLog rotateop(isForce);
+ VMThread::execute(&rotateop);
+
+ return JNI_OK;
+}
+
// Table to map operation names to functions.
// names must be of length <= AttachOperation::name_length_max
@@ -366,6 +395,7 @@
{ "inspectheap", heap_inspection },
{ "setflag", set_flag },
{ "printflag", print_flag },
+ { "rotategclog", rotate_gclog },
{ NULL, NULL }
};
diff -r 0fa3ace511fe src/share/vm/utilities/ostream.cpp
--- a/src/share/vm/utilities/ostream.cpp Thu Sep 01 13:54:24 2011 -0700
+++ b/src/share/vm/utilities/ostream.cpp Fri Sep 09 15:45:32 2011 +0900
@@ -421,8 +421,13 @@
// write to gc log file at safepoint. If in future, changes made for mutator threads or
// concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
// must be synchronized.
-void rotatingFileStream::rotate_log() {
- if (_bytes_writen < (jlong)GCLogFileSize) return;
+void rotatingFileStream::rotate_log(bool isForce) {
+
+ if(!isForce &&
+ ((GCLogFileSize > 0) && (_bytes_writen < (jlong)GCLogFileSize))){
+ return;
+ }
+
#ifdef ASSERT
Thread *thread = Thread::current();
assert(thread == NULL ||
diff -r 0fa3ace511fe src/share/vm/utilities/ostream.hpp
--- a/src/share/vm/utilities/ostream.hpp Thu Sep 01 13:54:24 2011 -0700
+++ b/src/share/vm/utilities/ostream.hpp Fri Sep 09 15:45:32 2011 +0900
@@ -110,7 +110,7 @@
// flushing
virtual void flush() {}
virtual void write(const char* str, size_t len) = 0;
- virtual void rotate_log() {} // GC log rotation
+ virtual void rotate_log(bool isForce) {} // GC log rotation
virtual ~outputStream() {} // close properly on deletion
void dec_cr() { dec(); cr(); }
@@ -223,7 +223,7 @@
rotatingFileStream(FILE* file) : fileStream(file) {}
~rotatingFileStream();
virtual void write(const char* c, size_t len);
- virtual void rotate_log();
+ virtual void rotate_log(bool isForce);
};
void ostream_init();
More information about the hotspot-gc-dev
mailing list