changeset 1781:97fbf5beff7b

Merge
author johnc
date Thu, 16 Sep 2010 13:45:55 -0700
parents 8a8a7a014a12 (diff) 432d823638f7 (current diff)
children 18c378513575 3babdb042f25 8b10f48633dc
files
diffstat 5 files changed, 88 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/make/linux/makefiles/sa.make	Wed Sep 15 10:39:13 2010 -0700
+++ b/make/linux/makefiles/sa.make	Thu Sep 16 13:45:55 2010 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,9 @@
 AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
 AGENT_FILES2 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES2))
 
+AGENT_FILES1_LIST := $(GENERATED)/agent1.classes.list
+AGENT_FILES2_LIST := $(GENERATED)/agent2.classes.list
+
 SA_CLASSDIR = $(GENERATED)/saclasses
 
 SA_BUILD_VERSION_PROP = "sun.jvm.hotspot.runtime.VM.saBuildVersion=$(SA_BUILD_VERSION)"
@@ -65,7 +68,7 @@
 	   $(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \
 	fi
 
-$(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
+$(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2) agent_files_preclean
 	$(QUIETLY) echo "Making $@"
 	$(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \
 	  echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
@@ -79,10 +82,13 @@
 	$(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \
 	  mkdir -p $(SA_CLASSDIR);        \
 	fi
-
-	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES1)
-	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES2)
-
+	
+	$(foreach file,$(AGENT_FILES1),$(shell echo $(file) >> $(AGENT_FILES1_LIST)))
+	$(foreach file,$(AGENT_FILES2),$(shell echo $(file) >> $(AGENT_FILES2_LIST)))
+	
+	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES1_LIST)
+	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES2_LIST)
+	
 	$(QUIETLY) $(REMOTE) $(COMPILE.RMIC)  -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
 	$(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
 	$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
@@ -98,6 +104,10 @@
 	$(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
 	$(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.sparc.SPARCThreadContext
 
+agent_files_preclean:
+	rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST)
+
 clean:
 	rm -rf $(SA_CLASSDIR)
 	rm -rf $(GENERATED)/sa-jdi.jar
+	rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST)
--- a/make/solaris/makefiles/sa.make	Wed Sep 15 10:39:13 2010 -0700
+++ b/make/solaris/makefiles/sa.make	Thu Sep 16 13:45:55 2010 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,9 @@
 AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
 AGENT_FILES2 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES2))
 
+AGENT_FILES1_LIST := $(GENERATED)/agent1.classes.list
+AGENT_FILES2_LIST := $(GENERATED)/agent2.classes.list
+
 SA_CLASSDIR = $(GENERATED)/saclasses
 
 SA_BUILD_VERSION_PROP = "sun.jvm.hotspot.runtime.VM.saBuildVersion=$(SA_BUILD_VERSION)"
@@ -56,7 +59,7 @@
 	   $(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \
 	fi
 
-$(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2)
+$(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2) agent_files_preclean
 	$(QUIETLY) echo "Making $@";
 	$(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \
 	   echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
@@ -70,8 +73,12 @@
 	$(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \
 	  mkdir -p $(SA_CLASSDIR);        \
 	fi
-	$(QUIETLY) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES1)
-	$(QUIETLY) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES2)
+	
+	$(foreach file,$(AGENT_FILES1),$(shell echo $(file) >> $(AGENT_FILES1_LIST)))
+	$(foreach file,$(AGENT_FILES2),$(shell echo $(file) >> $(AGENT_FILES2_LIST)))
+	
+	$(QUIETLY) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES1_LIST)
+	$(QUIETLY) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES2_LIST)
 	
 	$(QUIETLY) $(COMPILE.RMIC)  -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
 	$(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
@@ -85,6 +92,10 @@
 	$(QUIETLY) $(RUN.JAR) uf $@ -C $(AGENT_SRC_DIR) META-INF/services/com.sun.jdi.connect.Connector
 	$(QUIETLY) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal
 
+agent_files_preclean:
+	rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST)
+
 clean:
 	rm -rf $(SA_CLASSDIR)
 	rm -rf $(GENERATED)/sa-jdi.jar
+	rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST)
--- a/src/share/vm/services/heapDumper.cpp	Wed Sep 15 10:39:13 2010 -0700
+++ b/src/share/vm/services/heapDumper.cpp	Thu Sep 16 13:45:55 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1305,6 +1305,8 @@
   static VM_HeapDumper* _global_dumper;
   static DumpWriter*    _global_writer;
   DumpWriter*           _local_writer;
+  JavaThread*           _oome_thread;
+  methodOop             _oome_constructor;
   bool _gc_before_heap_dump;
   bool _is_segmented_dump;
   jlong _dump_start;
@@ -1366,7 +1368,7 @@
   void end_of_dump();
 
  public:
-  VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump) :
+  VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump, bool oome) :
     VM_GC_Operation(0 /* total collections,      dummy, ignored */,
                     0 /* total full collections, dummy, ignored */,
                     gc_before_heap_dump) {
@@ -1377,6 +1379,18 @@
     _klass_map = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(INITIAL_CLASS_COUNT, true);
     _stack_traces = NULL;
     _num_threads = 0;
+    if (oome) {
+      assert(!Thread::current()->is_VM_thread(), "Dump from OutOfMemoryError cannot be called by the VMThread");
+      // get OutOfMemoryError zero-parameter constructor
+      instanceKlass* oome_ik = instanceKlass::cast(SystemDictionary::OutOfMemoryError_klass());
+      _oome_constructor = oome_ik->find_method(vmSymbols::object_initializer_name(),
+                                                          vmSymbols::void_method_signature());
+      // get thread throwing OOME when generating the heap dump at OOME
+      _oome_thread = JavaThread::current();
+    } else {
+      _oome_thread = NULL;
+      _oome_constructor = NULL;
+    }
   }
   ~VM_HeapDumper() {
     if (_stack_traces != NULL) {
@@ -1557,7 +1571,11 @@
     frame f = java_thread->last_frame();
     vframe* vf = vframe::new_vframe(&f, &reg_map, java_thread);
     frame* last_entry_frame = NULL;
+    int extra_frames = 0;
 
+    if (java_thread == _oome_thread && _oome_constructor != NULL) {
+      extra_frames++;
+    }
     while (vf != NULL) {
       blk.set_frame_number(stack_depth);
       if (vf->is_java_frame()) {
@@ -1574,7 +1592,7 @@
                 writer()->write_u1(HPROF_GC_ROOT_JAVA_FRAME);
                 writer()->write_objectID(o);
                 writer()->write_u4(thread_serial_num);
-                writer()->write_u4((u4) stack_depth);
+                writer()->write_u4((u4) (stack_depth + extra_frames));
               }
             }
           }
@@ -1764,6 +1782,17 @@
       // write HPROF_FRAME records for this thread's stack trace
       int depth = stack_trace->get_stack_depth();
       int thread_frame_start = frame_serial_num;
+      int extra_frames = 0;
+      // write fake frame that makes it look like the thread, which caused OOME,
+      // is in the OutOfMemoryError zero-parameter constructor
+      if (thread == _oome_thread && _oome_constructor != NULL) {
+        int oome_serial_num = _klass_map->find(Klass::cast(_oome_constructor->method_holder()));
+        // the class serial number starts from 1
+        assert(oome_serial_num > 0, "OutOfMemoryError class not found");
+        DumperSupport::dump_stack_frame(writer(), ++frame_serial_num, oome_serial_num,
+                                        _oome_constructor, 0);
+        extra_frames++;
+      }
       for (int j=0; j < depth; j++) {
         StackFrameInfo* frame = stack_trace->stack_frame_at(j);
         methodOop m = frame->method();
@@ -1772,6 +1801,7 @@
         assert(class_serial_num > 0, "class not found");
         DumperSupport::dump_stack_frame(writer(), ++frame_serial_num, class_serial_num, m, frame->bci());
       }
+      depth += extra_frames;
 
       // write HPROF_TRACE record for one thread
       DumperSupport::write_header(writer(), HPROF_TRACE, 3*sizeof(u4) + depth*oopSize);
@@ -1808,7 +1838,7 @@
   }
 
   // generate the dump
-  VM_HeapDumper dumper(&writer, _gc_before_heap_dump);
+  VM_HeapDumper dumper(&writer, _gc_before_heap_dump, _oome);
   if (Thread::current()->is_VM_thread()) {
     assert(SafepointSynchronize::is_at_safepoint(), "Expected to be called at a safepoint");
     dumper.doit();
@@ -1869,12 +1899,22 @@
   }
 }
 
+// Called by out-of-memory error reporting by a single Java thread
+// outside of a JVM safepoint
+void HeapDumper::dump_heap_from_oome() {
+  HeapDumper::dump_heap(true);
+}
+
 // Called by error reporting by a single Java thread outside of a JVM safepoint,
 // or by heap dumping by the VM thread during a (GC) safepoint. Thus, these various
 // callers are strictly serialized and guaranteed not to interfere below. For more
 // general use, however, this method will need modification to prevent
 // inteference when updating the static variables base_path and dump_file_seq below.
 void HeapDumper::dump_heap() {
+  HeapDumper::dump_heap(false);
+}
+
+void HeapDumper::dump_heap(bool oome) {
   static char base_path[JVM_MAXPATHLEN] = {'\0'};
   static uint dump_file_seq = 0;
   char   my_path[JVM_MAXPATHLEN] = {'\0'};
@@ -1930,6 +1970,7 @@
   dump_file_seq++;   // increment seq number for next time we dump
 
   HeapDumper dumper(false /* no GC before heap dump */,
-                    true  /* send to tty */);
+                    true  /* send to tty */,
+                    oome  /* pass along out-of-memory-error flag */);
   dumper.dump(my_path);
 }
--- a/src/share/vm/services/heapDumper.hpp	Wed Sep 15 10:39:13 2010 -0700
+++ b/src/share/vm/services/heapDumper.hpp	Thu Sep 16 13:45:55 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,8 +39,12 @@
   char* _error;
   bool _print_to_tty;
   bool _gc_before_heap_dump;
+  bool _oome;
   elapsedTimer _t;
 
+  HeapDumper(bool gc_before_heap_dump, bool print_to_tty, bool oome) :
+    _gc_before_heap_dump(gc_before_heap_dump), _error(NULL), _print_to_tty(print_to_tty), _oome(oome) { }
+
   // string representation of error
   char* error() const                   { return _error; }
   void set_error(char* error);
@@ -51,11 +55,11 @@
   // internal timer.
   elapsedTimer* timer()                 { return &_t; }
 
+  static void dump_heap(bool oome);
+
  public:
   HeapDumper(bool gc_before_heap_dump) :
-    _gc_before_heap_dump(gc_before_heap_dump), _error(NULL), _print_to_tty(false) { }
-  HeapDumper(bool gc_before_heap_dump, bool print_to_tty) :
-    _gc_before_heap_dump(gc_before_heap_dump), _error(NULL), _print_to_tty(print_to_tty) { }
+    _gc_before_heap_dump(gc_before_heap_dump), _error(NULL), _print_to_tty(false), _oome(false) { }
 
   ~HeapDumper();
 
@@ -66,4 +70,6 @@
   char* error_as_C_string() const;
 
   static void dump_heap()    KERNEL_RETURN;
+
+  static void dump_heap_from_oome()    KERNEL_RETURN;
 };
--- a/src/share/vm/utilities/debug.cpp	Wed Sep 15 10:39:13 2010 -0700
+++ b/src/share/vm/utilities/debug.cpp	Thu Sep 16 13:45:55 2010 -0700
@@ -234,7 +234,7 @@
     // create heap dump before OnOutOfMemoryError commands are executed
     if (HeapDumpOnOutOfMemoryError) {
       tty->print_cr("java.lang.OutOfMemoryError: %s", message);
-      HeapDumper::dump_heap();
+      HeapDumper::dump_heap_from_oome();
     }
 
     if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {