--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Jan 13 00:27:53 2012 -0800
@@ -63,8 +63,6 @@
private static int CLASS_STATE_FULLY_INITIALIZED;
private static int CLASS_STATE_INITIALIZATION_ERROR;
- private static int IS_MARKED_DEPENDENT_MASK;
-
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("instanceKlass");
arrayKlasses = new OopField(type.getOopField("_array_klasses"), Oop.getHeaderSize());
@@ -92,7 +90,7 @@
staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), Oop.getHeaderSize());
staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), Oop.getHeaderSize());
nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), Oop.getHeaderSize());
- miscFlags = new CIntField(type.getCIntegerField("_misc_flags"), Oop.getHeaderSize());
+ isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), Oop.getHeaderSize());
initState = new CIntField(type.getCIntegerField("_init_state"), Oop.getHeaderSize());
vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), Oop.getHeaderSize());
itableLen = new CIntField(type.getCIntegerField("_itable_len"), Oop.getHeaderSize());
@@ -120,8 +118,6 @@
CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("instanceKlass::fully_initialized").intValue();
CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("instanceKlass::initialization_error").intValue();
- IS_MARKED_DEPENDENT_MASK = db.lookupIntConstant("instanceKlass::IS_MARKED_DEPENDENT").intValue();
-
}
InstanceKlass(OopHandle handle, ObjectHeap heap) {
@@ -155,7 +151,7 @@
private static CIntField staticFieldSize;
private static CIntField staticOopFieldCount;
private static CIntField nonstaticOopMapSize;
- private static CIntField miscFlags;
+ private static CIntField isMarkedDependent;
private static CIntField initState;
private static CIntField vtableLen;
private static CIntField itableLen;
@@ -337,7 +333,7 @@
public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); }
public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); }
- public boolean getIsMarkedDependent() { return (miscFlags.getValue(this) & IS_MARKED_DEPENDENT_MASK) != 0; }
+ public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; }
public long getVtableLen() { return vtableLen.getValue(this); }
public long getItableLen() { return itableLen.getValue(this); }
public Symbol getGenericSignature() { return getSymbol(genericSignature); }
@@ -528,7 +524,7 @@
visitor.doCInt(staticFieldSize, true);
visitor.doCInt(staticOopFieldCount, true);
visitor.doCInt(nonstaticOopMapSize, true);
- visitor.doCInt(miscFlags, true);
+ visitor.doCInt(isMarkedDependent, true);
visitor.doCInt(initState, true);
visitor.doCInt(vtableLen, true);
visitor.doCInt(itableLen, true);
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Jan 13 00:27:53 2012 -0800
@@ -296,6 +296,7 @@
template(finalize_method_name, "finalize") \
template(reference_lock_name, "lock") \
template(reference_discovered_name, "discovered") \
+ template(run_finalization_name, "runFinalization") \
template(run_finalizers_on_exit_name, "runFinalizersOnExit") \
template(uncaughtException_name, "uncaughtException") \
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
--- a/hotspot/src/share/vm/code/dependencies.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/code/dependencies.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -1631,7 +1631,7 @@
for (ContextStream str(*this); str.next(); ) {
klassOop d = str.klass();
assert(!instanceKlass::cast(d)->is_marked_dependent(), "checking");
- instanceKlass::cast(d)->set_is_marked_dependent();
+ instanceKlass::cast(d)->set_is_marked_dependent(true);
}
}
@@ -1640,7 +1640,7 @@
// Unmark transitive interfaces
for (ContextStream str(*this); str.next(); ) {
klassOop d = str.klass();
- instanceKlass::cast(d)->clear_is_marked_dependent();
+ instanceKlass::cast(d)->set_is_marked_dependent(false);
}
}
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Jan 13 00:27:53 2012 -0800
@@ -231,6 +231,10 @@
u2 _java_fields_count; // The number of declared Java fields
int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
+ bool _is_marked_dependent; // used for marking during flushing and deoptimization
+ bool _rewritten; // methods rewritten.
+ bool _has_nonstatic_fields; // for sizing with UseCompressedOops
+ bool _should_verify_class; // allow caching of preverification
u2 _minor_version; // minor version number of class file
u2 _major_version; // major version number of class file
Thread* _init_thread; // Pointer to current thread doing initialization (to handle recusive initialization)
@@ -261,19 +265,6 @@
// _idnum_allocated_count.
u1 _init_state; // state of class
- // Compact the following four boolean flags into 1-bit each. These four flags
- // were defined as separate boolean fields and each was 1-byte before. Since
- // there are 2 bytes unused after the _idnum_allocated_count field, place the
- // _misc_flags field after _idnum_allocated_count to utilize the unused bits
- // and save total 4-bytes.
- enum {
- IS_MARKED_DEPENDENT = 0x1, // used for marking during flushing and deoptimization
- REWRITTEN = 0x2, // methods rewritten.
- HAS_NONSTATIC_FIELDS = 0x4, // for sizing with UseCompressedOops
- SHOULD_VERIFY_CLASS = 0x8 // allow caching of preverification
- };
- u1 _misc_flags;
-
// embedded Java vtable follows here
// embedded Java itables follows here
// embedded static fields follows here
@@ -283,14 +274,8 @@
friend class SystemDictionary;
public:
- bool has_nonstatic_fields() const { return (_misc_flags & HAS_NONSTATIC_FIELDS) != 0; }
- void set_has_nonstatic_fields(bool b) {
- if (b) {
- _misc_flags |= HAS_NONSTATIC_FIELDS;
- } else {
- _misc_flags &= ~HAS_NONSTATIC_FIELDS;
- }
- }
+ bool has_nonstatic_fields() const { return _has_nonstatic_fields; }
+ void set_has_nonstatic_fields(bool b) { _has_nonstatic_fields = b; }
// field sizes
int nonstatic_field_size() const { return _nonstatic_field_size; }
@@ -398,23 +383,15 @@
bool is_in_error_state() const { return _init_state == initialization_error; }
bool is_reentrant_initialization(Thread *thread) { return thread == _init_thread; }
ClassState init_state() { return (ClassState)_init_state; }
- bool is_rewritten() const { return (_misc_flags & REWRITTEN) != 0; }
+ bool is_rewritten() const { return _rewritten; }
// defineClass specified verification
- bool should_verify_class() const { return (_misc_flags & SHOULD_VERIFY_CLASS) != 0; }
- void set_should_verify_class(bool value) {
- if (value) {
- _misc_flags |= SHOULD_VERIFY_CLASS;
- } else {
- _misc_flags &= ~SHOULD_VERIFY_CLASS;
- }
- }
-
+ bool should_verify_class() const { return _should_verify_class; }
+ void set_should_verify_class(bool value) { _should_verify_class = value; }
// marking
- bool is_marked_dependent() const { return (_misc_flags & IS_MARKED_DEPENDENT) != 0; }
- void set_is_marked_dependent() { _misc_flags |= IS_MARKED_DEPENDENT; }
- void clear_is_marked_dependent() { _misc_flags &= ~IS_MARKED_DEPENDENT; }
+ bool is_marked_dependent() const { return _is_marked_dependent; }
+ void set_is_marked_dependent(bool value) { _is_marked_dependent = value; }
// initialization (virtuals from Klass)
bool should_be_initialized() const; // means that initialize should be called
@@ -784,7 +761,7 @@
#else
void set_init_state(ClassState state) { _init_state = (u1)state; }
#endif
- void set_rewritten() { _misc_flags |= REWRITTEN; }
+ void set_rewritten() { _rewritten = true; }
void set_init_thread(Thread *thread) { _init_thread = thread; }
u2 idnum_allocated_count() const { return _idnum_allocated_count; }
--- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -399,7 +399,7 @@
ik->set_inner_classes(NULL);
ik->set_static_oop_field_count(0);
ik->set_nonstatic_field_size(0);
- ik->clear_is_marked_dependent();
+ ik->set_is_marked_dependent(false);
ik->set_init_state(instanceKlass::allocated);
ik->set_init_thread(NULL);
ik->set_reference_type(rt);
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -2330,7 +2330,7 @@
#ifndef PRODUCT
// -Xprintflags
} else if (match_option(option, "-Xprintflags", &tail)) {
- CommandLineFlags::printFlags();
+ CommandLineFlags::printFlags(tty, false);
vm_exit(0);
#endif
// -D
@@ -2978,13 +2978,13 @@
IgnoreUnrecognizedVMOptions = false;
}
if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) {
- CommandLineFlags::printFlags();
+ CommandLineFlags::printFlags(tty, false);
vm_exit(0);
}
#ifndef PRODUCT
if (match_option(option, "-XX:+PrintFlagsWithComments", &tail)) {
- CommandLineFlags::printFlags(true);
+ CommandLineFlags::printFlags(tty, true);
vm_exit(0);
}
#endif
@@ -3180,7 +3180,7 @@
#endif
if (PrintCommandLineFlags) {
- CommandLineFlags::printSetFlags();
+ CommandLineFlags::printSetFlags(tty);
}
// Apply CPU specific policy for the BiasedLocking
--- a/hotspot/src/share/vm/runtime/globals.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/runtime/globals.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -488,7 +488,7 @@
}
}
-void CommandLineFlags::printSetFlags() {
+void CommandLineFlags::printSetFlags(outputStream* out) {
// Print which flags were set on the command line
// note: this method is called before the thread structure is in place
// which means resource allocation cannot be used.
@@ -507,11 +507,11 @@
// Print
for (int i = 0; i < length; i++) {
if (array[i]->origin /* naked field! */) {
- array[i]->print_as_flag(tty);
- tty->print(" ");
+ array[i]->print_as_flag(out);
+ out->print(" ");
}
}
- tty->cr();
+ out->cr();
FREE_C_HEAP_ARRAY(Flag*, array);
}
@@ -524,7 +524,7 @@
#endif // PRODUCT
-void CommandLineFlags::printFlags(bool withComments) {
+void CommandLineFlags::printFlags(outputStream* out, bool withComments) {
// Print the flags sorted by name
// note: this method is called before the thread structure is in place
// which means resource allocation cannot be used.
@@ -541,10 +541,10 @@
qsort(array, length, sizeof(Flag*), compare_flags);
// Print
- tty->print_cr("[Global flags]");
+ out->print_cr("[Global flags]");
for (int i = 0; i < length; i++) {
if (array[i]->is_unlocked()) {
- array[i]->print_on(tty, withComments);
+ array[i]->print_on(out, withComments);
}
}
FREE_C_HEAP_ARRAY(Flag*, array);
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Jan 13 00:27:53 2012 -0800
@@ -326,9 +326,9 @@
// Returns false if name is not a command line flag.
static bool wasSetOnCmdline(const char* name, bool* value);
- static void printSetFlags();
+ static void printSetFlags(outputStream* out);
- static void printFlags(bool withComments = false );
+ static void printFlags(outputStream* out, bool withComments);
static void verify() PRODUCT_RETURN;
};
--- a/hotspot/src/share/vm/runtime/init.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/runtime/init.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -140,7 +140,7 @@
// All the flags that get adjusted by VM_Version_init and os::init_2
// have been set so dump the flags now.
if (PrintFlagsFinal) {
- CommandLineFlags::printFlags();
+ CommandLineFlags::printFlags(tty, false);
}
return JNI_OK;
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -307,7 +307,7 @@
nonstatic_field(instanceKlass, _static_field_size, int) \
nonstatic_field(instanceKlass, _static_oop_field_count, u2) \
nonstatic_field(instanceKlass, _nonstatic_oop_map_size, int) \
- nonstatic_field(instanceKlass, _misc_flags, u1) \
+ nonstatic_field(instanceKlass, _is_marked_dependent, bool) \
nonstatic_field(instanceKlass, _minor_version, u2) \
nonstatic_field(instanceKlass, _major_version, u2) \
nonstatic_field(instanceKlass, _init_state, u1) \
@@ -2386,7 +2386,6 @@
declare_constant(instanceKlass::being_initialized) \
declare_constant(instanceKlass::fully_initialized) \
declare_constant(instanceKlass::initialization_error) \
- declare_constant(instanceKlass::IS_MARKED_DEPENDENT) \
\
/*********************************/ \
/* Symbol* - symbol max length */ \
--- a/hotspot/src/share/vm/services/attachListener.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/services/attachListener.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -99,6 +99,7 @@
}
// Implementation of "properties" command.
+// See also: PrintSystemPropertiesDCmd class
static jint get_system_properties(AttachOperation* op, outputStream* out) {
return get_properties(op, out, vmSymbols::serializePropertiesToByteArray_name());
}
@@ -127,6 +128,7 @@
}
// Implementation of "threaddump" command - essentially a remote ctrl-break
+// See also: ThreadDumpDCmd class
//
static jint thread_dump(AttachOperation* op, outputStream* out) {
bool print_concurrent_locks = false;
@@ -158,6 +160,7 @@
DCmd::parse_and_execute(out, op->arg(0), ' ', THREAD);
if (HAS_PENDING_EXCEPTION) {
java_lang_Throwable::print(PENDING_EXCEPTION, out);
+ out->cr();
CLEAR_PENDING_EXCEPTION;
// The exception has been printed on the output stream
// If the JVM returns JNI_ERR, the attachAPI throws a generic I/O
@@ -169,6 +172,7 @@
#ifndef SERVICES_KERNEL // Heap dumping not supported
// Implementation of "dumpheap" command.
+// See also: HeapDumpDCmd class
//
// Input arguments :-
// arg0: Name of the dump file
@@ -211,6 +215,7 @@
#endif // SERVICES_KERNEL
// Implementation of "inspectheap" command
+// See also: ClassHistogramDCmd class
//
// Input arguments :-
// arg0: "-live" or "-all"
@@ -354,6 +359,7 @@
}
// Implementation of "printflag" command
+// See also: PrintVMFlagsDCmd class
static jint print_flag(AttachOperation* op, outputStream* out) {
const char* name = NULL;
if ((name = op->arg(0)) == NULL) {
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -23,11 +23,15 @@
*/
#include "precompiled.hpp"
+#include "gc_implementation/shared/vmGCOperations.hpp"
+#include "runtime/javaCalls.hpp"
#include "services/diagnosticArgument.hpp"
#include "services/diagnosticCommand.hpp"
#include "services/diagnosticFramework.hpp"
+#include "services/heapDumper.hpp"
+#include "services/management.hpp"
-HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmd(output, heap),
+HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap),
_all("-all", "Show help for all commands", "BOOLEAN", false, "false"),
_cmd("command name", "The name of the command for which we want help",
"STRING", false) {
@@ -35,14 +39,6 @@
_dcmdparser.add_dcmd_argument(&_cmd);
};
-void HelpDCmd::parse(CmdLine* line, char delim, TRAPS) {
- _dcmdparser.parse(line, delim, CHECK);
-}
-
-void HelpDCmd::print_help(outputStream* out) {
- _dcmdparser.print_help(out, name());
-}
-
void HelpDCmd::execute(TRAPS) {
if (_all.value()) {
GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list();
@@ -66,10 +62,11 @@
factory->is_enabled() ? "" : " [disabled]");
output()->print_cr(factory->description());
output()->print_cr("\nImpact: %s", factory->impact());
+ output()->cr();
cmd = factory->create_resource_instance(output());
if (cmd != NULL) {
DCmdMark mark(cmd);
- cmd->print_help(output());
+ cmd->print_help(factory->name());
}
} else {
output()->print_cr("Help unavailable : '%s' : No such command", _cmd.value());
@@ -90,14 +87,6 @@
}
}
-void HelpDCmd::reset(TRAPS) {
- _dcmdparser.reset(CHECK);
-}
-
-void HelpDCmd::cleanup() {
- _dcmdparser.cleanup();
-}
-
int HelpDCmd::num_arguments() {
ResourceMark rm;
HelpDCmd* dcmd = new HelpDCmd(NULL, false);
@@ -109,14 +98,6 @@
}
}
-GrowableArray<const char*>* HelpDCmd::argument_name_array() {
- return _dcmdparser.argument_name_array();
-}
-
-GrowableArray<DCmdArgumentInfo*>* HelpDCmd::argument_info_array() {
- return _dcmdparser.argument_info_array();
-}
-
void VersionDCmd::execute(TRAPS) {
output()->print_cr("%s version %s", Abstract_VM_Version::vm_name(),
Abstract_VM_Version::vm_release());
@@ -129,3 +110,210 @@
jdk_version.minor_version());
}
}
+
+PrintVMFlagsDCmd::PrintVMFlagsDCmd(outputStream* output, bool heap) :
+ DCmdWithParser(output, heap),
+ _all("-all", "Print all flags supported by the VM", "BOOLEAN", false, "false") {
+ _dcmdparser.add_dcmd_option(&_all);
+}
+
+void PrintVMFlagsDCmd::execute(TRAPS) {
+ if (_all.value()) {
+ CommandLineFlags::printFlags(output(), true);
+ } else {
+ CommandLineFlags::printSetFlags(output());
+ }
+}
+
+int PrintVMFlagsDCmd::num_arguments() {
+ ResourceMark rm;
+ PrintVMFlagsDCmd* dcmd = new PrintVMFlagsDCmd(NULL, false);
+ if (dcmd != NULL) {
+ DCmdMark mark(dcmd);
+ return dcmd->_dcmdparser.num_arguments();
+ } else {
+ return 0;
+ }
+}
+
+void PrintSystemPropertiesDCmd::execute(TRAPS) {
+ // load sun.misc.VMSupport
+ Symbol* klass = vmSymbols::sun_misc_VMSupport();
+ klassOop k = SystemDictionary::resolve_or_fail(klass, true, CHECK);
+ instanceKlassHandle ik (THREAD, k);
+ if (ik->should_be_initialized()) {
+ ik->initialize(THREAD);
+ }
+ if (HAS_PENDING_EXCEPTION) {
+ java_lang_Throwable::print(PENDING_EXCEPTION, output());
+ output()->cr();
+ CLEAR_PENDING_EXCEPTION;
+ return;
+ }
+
+ // invoke the serializePropertiesToByteArray method
+ JavaValue result(T_OBJECT);
+ JavaCallArguments args;
+
+ Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature();
+ JavaCalls::call_static(&result,
+ ik,
+ vmSymbols::serializePropertiesToByteArray_name(),
+ signature,
+ &args,
+ THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ java_lang_Throwable::print(PENDING_EXCEPTION, output());
+ output()->cr();
+ CLEAR_PENDING_EXCEPTION;
+ return;
+ }
+
+ // The result should be a [B
+ oop res = (oop)result.get_jobject();
+ assert(res->is_typeArray(), "just checking");
+ assert(typeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
+
+ // copy the bytes to the output stream
+ typeArrayOop ba = typeArrayOop(res);
+ jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
+ output()->print_raw((const char*)addr, ba->length());
+}
+
+VMUptimeDCmd::VMUptimeDCmd(outputStream* output, bool heap) :
+ DCmdWithParser(output, heap),
+ _date("-date", "Add a prefix with current date", "BOOLEAN", false, "false") {
+ _dcmdparser.add_dcmd_option(&_date);
+}
+
+void VMUptimeDCmd::execute(TRAPS) {
+ if (_date.value()) {
+ output()->date_stamp(true, "", ": ");
+ }
+ output()->time_stamp().update_to(tty->time_stamp().ticks());
+ output()->stamp();
+ output()->print_cr(" s");
+}
+
+int VMUptimeDCmd::num_arguments() {
+ ResourceMark rm;
+ VMUptimeDCmd* dcmd = new VMUptimeDCmd(NULL, false);
+ if (dcmd != NULL) {
+ DCmdMark mark(dcmd);
+ return dcmd->_dcmdparser.num_arguments();
+ } else {
+ return 0;
+ }
+}
+
+void SystemGCDCmd::execute(TRAPS) {
+ Universe::heap()->collect(GCCause::_java_lang_system_gc);
+}
+
+void RunFinalizationDCmd::execute(TRAPS) {
+ klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(),
+ true, CHECK);
+ instanceKlassHandle klass(THREAD, k);
+ JavaValue result(T_VOID);
+ JavaCalls::call_static(&result, klass,
+ vmSymbols::run_finalization_name(),
+ vmSymbols::void_method_signature(), CHECK);
+}
+
+#ifndef SERVICES_KERNEL // Heap dumping not supported
+HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
+ DCmdWithParser(output, heap),
+ _filename("filename","Name of the dump file", "STRING",true),
+ _all("-all", "Dump all objects, including unreachable objects",
+ "BOOLEAN", false, "false") {
+ _dcmdparser.add_dcmd_option(&_all);
+ _dcmdparser.add_dcmd_argument(&_filename);
+}
+
+void HeapDumpDCmd::execute(TRAPS) {
+ // Request a full GC before heap dump if _all is false
+ // This helps reduces the amount of unreachable objects in the dump
+ // and makes it easier to browse.
+ HeapDumper dumper(!_all.value() /* request GC if _all is false*/);
+ int res = dumper.dump(_filename.value());
+ if (res == 0) {
+ output()->print_cr("Heap dump file created");
+ } else {
+ // heap dump failed
+ ResourceMark rm;
+ char* error = dumper.error_as_C_string();
+ if (error == NULL) {
+ output()->print_cr("Dump failed - reason unknown");
+ } else {
+ output()->print_cr("%s", error);
+ }
+ }
+}
+
+int HeapDumpDCmd::num_arguments() {
+ ResourceMark rm;
+ HeapDumpDCmd* dcmd = new HeapDumpDCmd(NULL, false);
+ if (dcmd != NULL) {
+ DCmdMark mark(dcmd);
+ return dcmd->_dcmdparser.num_arguments();
+ } else {
+ return 0;
+ }
+}
+#endif // SERVICES_KERNEL
+
+ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :
+ DCmdWithParser(output, heap),
+ _all("-all", "Inspect all objects, including unreachable objects",
+ "BOOLEAN", false, "false") {
+ _dcmdparser.add_dcmd_option(&_all);
+}
+
+void ClassHistogramDCmd::execute(TRAPS) {
+ VM_GC_HeapInspection heapop(output(),
+ !_all.value() /* request full gc if false */,
+ true /* need_prologue */);
+ VMThread::execute(&heapop);
+}
+
+int ClassHistogramDCmd::num_arguments() {
+ ResourceMark rm;
+ ClassHistogramDCmd* dcmd = new ClassHistogramDCmd(NULL, false);
+ if (dcmd != NULL) {
+ DCmdMark mark(dcmd);
+ return dcmd->_dcmdparser.num_arguments();
+ } else {
+ return 0;
+ }
+}
+
+ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :
+ DCmdWithParser(output, heap),
+ _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false") {
+ _dcmdparser.add_dcmd_option(&_locks);
+}
+
+void ThreadDumpDCmd::execute(TRAPS) {
+ // thread stacks
+ VM_PrintThreads op1(output(), _locks.value());
+ VMThread::execute(&op1);
+
+ // JNI global handles
+ VM_PrintJNI op2(output());
+ VMThread::execute(&op2);
+
+ // Deadlock detection
+ VM_FindDeadlocks op3(output());
+ VMThread::execute(&op3);
+}
+
+int ThreadDumpDCmd::num_arguments() {
+ ResourceMark rm;
+ ThreadDumpDCmd* dcmd = new ThreadDumpDCmd(NULL, false);
+ if (dcmd != NULL) {
+ DCmdMark mark(dcmd);
+ return dcmd->_dcmdparser.num_arguments();
+ } else {
+ return 0;
+ }
+}
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Fri Jan 13 00:27:53 2012 -0800
@@ -35,9 +35,8 @@
#include "services/diagnosticCommand.hpp"
#include "services/diagnosticFramework.hpp"
-class HelpDCmd : public DCmd {
+class HelpDCmd : public DCmdWithParser {
protected:
- DCmdParser _dcmdparser;
DCmdArgument<bool> _all;
DCmdArgument<char*> _cmd;
public:
@@ -50,13 +49,7 @@
}
static const char* impact() { return "Low: "; }
static int num_arguments();
- virtual void parse(CmdLine* line, char delim, TRAPS);
virtual void execute(TRAPS);
- virtual void reset(TRAPS);
- virtual void cleanup();
- virtual void print_help(outputStream* out);
- virtual GrowableArray<const char*>* argument_name_array();
- virtual GrowableArray<DCmdArgumentInfo*>* argument_info_array();
};
class VersionDCmd : public DCmd {
@@ -68,9 +61,156 @@
}
static const char* impact() { return "Low: "; }
static int num_arguments() { return 0; }
- virtual void parse(CmdLine* line, char delim, TRAPS) { }
+ virtual void execute(TRAPS);
+};
+
+class CommandLineDCmd : public DCmd {
+public:
+ CommandLineDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
+ static const char* name() { return "VM.command_line"; }
+ static const char* description() {
+ return "Print the command line used to start this VM instance.";
+ }
+ static const char* impact() { return "Low: "; }
+ static int num_arguments() { return 0; }
+ virtual void execute(TRAPS) {
+ Arguments::print_on(_output);
+ }
+};
+
+// See also: get_system_properties in attachListener.cpp
+class PrintSystemPropertiesDCmd : public DCmd {
+public:
+ PrintSystemPropertiesDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
+ static const char* name() { return "VM.system_properties"; }
+ static const char* description() {
+ return "Print system properties.";
+ }
+ static const char* impact() {
+ return "Low: ";
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(TRAPS);
+};
+
+// See also: print_flag in attachListener.cpp
+class PrintVMFlagsDCmd : public DCmdWithParser {
+protected:
+ DCmdArgument<bool> _all;
+public:
+ PrintVMFlagsDCmd(outputStream* output, bool heap);
+ static const char* name() { return "VM.flags"; }
+ static const char* description() {
+ return "Print VM flag options and their current values.";
+ }
+ static const char* impact() {
+ return "Low: ";
+ }
+ static int num_arguments();
+ virtual void execute(TRAPS);
+};
+
+class VMUptimeDCmd : public DCmdWithParser {
+protected:
+ DCmdArgument<bool> _date;
+public:
+ VMUptimeDCmd(outputStream* output, bool heap);
+ static const char* name() { return "VM.uptime"; }
+ static const char* description() {
+ return "Print VM uptime.";
+ }
+ static const char* impact() {
+ return "Low: ";
+ }
+ static int num_arguments();
virtual void execute(TRAPS);
- virtual void print_help(outputStream* out) { }
+};
+
+class SystemGCDCmd : public DCmd {
+public:
+ SystemGCDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
+ static const char* name() { return "GC.run"; }
+ static const char* description() {
+ return "Call java.lang.System.gc().";
+ }
+ static const char* impact() {
+ return "Medium: Depends on Java heap size and content.";
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(TRAPS);
+};
+
+class RunFinalizationDCmd : public DCmd {
+public:
+ RunFinalizationDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
+ static const char* name() { return "GC.run_finalization"; }
+ static const char* description() {
+ return "Call java.lang.System.runFinalization().";
+ }
+ static const char* impact() {
+ return "Medium: Depends on Java content.";
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(TRAPS);
+};
+
+#ifndef SERVICES_KERNEL // Heap dumping not supported
+// See also: dump_heap in attachListener.cpp
+class HeapDumpDCmd : public DCmdWithParser {
+protected:
+ DCmdArgument<char*> _filename;
+ DCmdArgument<bool> _all;
+public:
+ HeapDumpDCmd(outputStream* output, bool heap);
+ static const char* name() {
+ return "GC.heap_dump";
+ }
+ static const char* description() {
+ return "Generate a HPROF format dump of the Java heap.";
+ }
+ static const char* impact() {
+ return "High: Depends on Java heap size and content. "
+ "Request a full GC unless the '-all' option is specified.";
+ }
+ static int num_arguments();
+ virtual void execute(TRAPS);
+};
+#endif // SERVICES_KERNEL
+
+// See also: inspeactheap in attachListener.cpp
+class ClassHistogramDCmd : public DCmdWithParser {
+protected:
+ DCmdArgument<bool> _all;
+public:
+ ClassHistogramDCmd(outputStream* output, bool heap);
+ static const char* name() {
+ return "GC.class_histogram";
+ }
+ static const char* description() {
+ return "Provide statistics about the Java heap usage.";
+ }
+ static const char* impact() {
+ return "High: Depends on Java heap size and content.";
+ }
+ static int num_arguments();
+ virtual void execute(TRAPS);
+};
+
+// See also: thread_dump in attachListener.cpp
+class ThreadDumpDCmd : public DCmdWithParser {
+protected:
+ DCmdArgument<bool> _locks;
+public:
+ ThreadDumpDCmd(outputStream* output, bool heap);
+ static const char* name() { return "Thread.print"; }
+ static const char* description() {
+ return "Print all threads with stacktraces.";
+ }
+ static const char* impact() {
+ return "Medium: Depends on the number of threads.";
+ }
+ static int num_arguments();
+ virtual void execute(TRAPS);
};
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/hotspot/src/share/vm/services/diagnosticFramework.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/services/diagnosticFramework.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -226,7 +226,7 @@
}
void DCmdParser::print_help(outputStream* out, const char* cmd_name) {
- out->print("\nSyntax : %s %s", cmd_name, _options == NULL ? "" : "[options]");
+ out->print("Syntax : %s %s", cmd_name, _options == NULL ? "" : "[options]");
GenDCmdArgument* arg = _arguments_list;
while (arg != NULL) {
if (arg->is_mandatory()) {
@@ -373,6 +373,30 @@
}
}
+void DCmdWithParser::parse(CmdLine* line, char delim, TRAPS) {
+ _dcmdparser.parse(line, delim, CHECK);
+}
+
+void DCmdWithParser::print_help(const char* name) {
+ _dcmdparser.print_help(output(), name);
+}
+
+void DCmdWithParser::reset(TRAPS) {
+ _dcmdparser.reset(CHECK);
+}
+
+void DCmdWithParser::cleanup() {
+ _dcmdparser.cleanup();
+}
+
+GrowableArray<const char*>* DCmdWithParser::argument_name_array() {
+ return _dcmdparser.argument_name_array();
+}
+
+GrowableArray<DCmdArgumentInfo*>* DCmdWithParser::argument_info_array() {
+ return _dcmdparser.argument_info_array();
+}
+
Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true);
DCmdFactory* DCmdFactory::factory(const char* name, size_t len) {
--- a/hotspot/src/share/vm/services/diagnosticFramework.hpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/services/diagnosticFramework.hpp Fri Jan 13 00:27:53 2012 -0800
@@ -241,8 +241,17 @@
static int num_arguments() { return 0; }
outputStream* output() { return _output; }
bool is_heap_allocated() { return _is_heap_allocated; }
- virtual void print_help(outputStream* out) { };
- virtual void parse(CmdLine* line, char delim, TRAPS) { }
+ virtual void print_help(const char* name) {
+ output()->print_cr("Syntax: %s", name);
+ }
+ virtual void parse(CmdLine* line, char delim, TRAPS) {
+ DCmdArgIter iter(line->args_addr(), line->args_len(), delim);
+ bool has_arg = iter.next(CHECK);
+ if (has_arg) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "Unknown argument in diagnostic command");
+ }
+ }
virtual void execute(TRAPS) { }
virtual void reset(TRAPS) { }
virtual void cleanup() { }
@@ -262,6 +271,25 @@
char delim, TRAPS);
};
+class DCmdWithParser : public DCmd {
+protected:
+ DCmdParser _dcmdparser;
+public:
+ DCmdWithParser (outputStream *output, bool heap=false) : DCmd(output, heap) { }
+ static const char* name() { return "No Name";}
+ static const char* description() { return "No Help";}
+ static const char* disabled_message() { return "Diagnostic command currently disabled"; }
+ static const char* impact() { return "Low: No impact"; }
+ static int num_arguments() { return 0; }
+ virtual void parse(CmdLine *line, char delim, TRAPS);
+ virtual void execute(TRAPS) { }
+ virtual void reset(TRAPS);
+ virtual void cleanup();
+ virtual void print_help(const char* name);
+ virtual GrowableArray<const char*>* argument_name_array();
+ virtual GrowableArray<DCmdArgumentInfo*>* argument_info_array();
+};
+
class DCmdMark : public StackObj {
DCmd* _ref;
public:
--- a/hotspot/src/share/vm/services/management.cpp Thu Jan 12 12:28:59 2012 -0800
+++ b/hotspot/src/share/vm/services/management.cpp Fri Jan 13 00:27:53 2012 -0800
@@ -118,8 +118,22 @@
#endif // SERVICES_KERNEL
_optional_support.isThreadAllocatedMemorySupported = 1;
+ // Registration of the diagnostic commands
+ // First boolean argument specifies if the command is enabled
+ // Second boolean argument specifies if the command is hidden
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HelpDCmd>(true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VersionDCmd>(true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CommandLineDCmd>(true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintSystemPropertiesDCmd>(true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<PrintVMFlagsDCmd>(true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(true, false));
+#ifndef SERVICES_KERNEL // Heap dumping not supported
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(true, false));
+#endif // SERVICES_KERNEL
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(true, false));
}
void Management::initialize(TRAPS) {