changeset 53997:a6182c464b31

8200613: SA: jstack throws UnmappedAddressException with a CDS core file Summary: Dump the closed archive heap space into the corefile on Linux by setting bit 2 of the coredump_filter file to dump the file backed private mappings. Reviewed-by: iklam, cjplummer, kevinw, coleenp
author jgeorge
date Wed, 12 Dec 2018 10:13:11 +0530
parents a35f7a452257
children d67b37917e82
files src/hotspot/os/linux/globals_linux.hpp src/hotspot/os/linux/os_linux.cpp src/hotspot/share/classfile/classLoader.cpp src/hotspot/share/classfile/classLoader.hpp test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java
diffstat 5 files changed, 53 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/os/linux/globals_linux.hpp	Tue Dec 11 19:55:27 2018 -0800
+++ b/src/hotspot/os/linux/globals_linux.hpp	Wed Dec 12 10:13:11 2018 +0530
@@ -67,6 +67,11 @@
           " of quotas (if set), when true. Otherwise, use the CPU"    \
           " shares value, provided it is less than quota.")             \
                                                                         \
+  diagnostic(bool, DumpPrivateMappingsInCore, true,                     \
+          "If true, sets bit 2 of /proc/PID/coredump_filter, thus "     \
+          "resulting in file-backed private mappings of the process to "\
+          "be dumped into the corefile, if UseSharedSpaces is true.")   \
+                                                                        \
   diagnostic(bool, UseCpuAllocPath, false,                              \
              "Use CPU_ALLOC code path in os::active_processor_count ")
 
--- a/src/hotspot/os/linux/os_linux.cpp	Tue Dec 11 19:55:27 2018 -0800
+++ b/src/hotspot/os/linux/os_linux.cpp	Wed Dec 12 10:13:11 2018 +0530
@@ -128,8 +128,12 @@
 // for timer info max values which include all bits
 #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
 
-#define LARGEPAGES_BIT (1 << 6)
-#define DAX_SHARED_BIT (1 << 8)
+enum CoredumpFilterBit {
+  FILE_BACKED_PVT_BIT = 1 << 2,
+  LARGEPAGES_BIT = 1 << 6,
+  DAX_SHARED_BIT = 1 << 8
+};
+
 ////////////////////////////////////////////////////////////////////////////////
 // global variables
 julong os::Linux::_physical_memory = 0;
@@ -1350,6 +1354,9 @@
 void os::abort(bool dump_core, void* siginfo, const void* context) {
   os::shutdown();
   if (dump_core) {
+    if (UseSharedSpaces && DumpPrivateMappingsInCore) {
+      ClassLoader::close_jrt_image();
+    }
 #ifndef PRODUCT
     fdStream out(defaultStream::output_fd());
     out.print_raw("Current thread is ");
@@ -3401,10 +3408,9 @@
 // - (bit 7) dax private memory
 // - (bit 8) dax shared memory
 //
-static void set_coredump_filter(bool largepages, bool dax_shared) {
+static void set_coredump_filter(CoredumpFilterBit bit) {
   FILE *f;
   long cdm;
-  bool filter_changed = false;
 
   if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) {
     return;
@@ -3415,17 +3421,11 @@
     return;
   }
 
+  long saved_cdm = cdm;
   rewind(f);
-
-  if (largepages && (cdm & LARGEPAGES_BIT) == 0) {
-    cdm |= LARGEPAGES_BIT;
-    filter_changed = true;
-  }
-  if (dax_shared && (cdm & DAX_SHARED_BIT) == 0) {
-    cdm |= DAX_SHARED_BIT;
-    filter_changed = true;
-  }
-  if (filter_changed) {
+  cdm |= bit;
+
+  if (cdm != saved_cdm) {
     fprintf(f, "%#lx", cdm);
   }
 
@@ -3564,7 +3564,7 @@
   size_t large_page_size = Linux::setup_large_page_size();
   UseLargePages          = Linux::setup_large_page_type(large_page_size);
 
-  set_coredump_filter(true /*largepages*/, false /*dax_shared*/);
+  set_coredump_filter(LARGEPAGES_BIT);
 }
 
 #ifndef SHM_HUGETLB
@@ -5072,8 +5072,13 @@
   prio_init();
 
   if (!FLAG_IS_DEFAULT(AllocateHeapAt)) {
-    set_coredump_filter(false /*largepages*/, true /*dax_shared*/);
-  }
+    set_coredump_filter(DAX_SHARED_BIT);
+  }
+
+  if (UseSharedSpaces && DumpPrivateMappingsInCore) {
+    set_coredump_filter(FILE_BACKED_PVT_BIT);
+  }
+
   return JNI_OK;
 }
 
--- a/src/hotspot/share/classfile/classLoader.cpp	Tue Dec 11 19:55:27 2018 -0800
+++ b/src/hotspot/share/classfile/classLoader.cpp	Wed Dec 12 10:13:11 2018 +0530
@@ -363,6 +363,13 @@
   }
 }
 
+void ClassPathImageEntry::close_jimage() {
+  if (_jimage != NULL) {
+    (*JImageClose)(_jimage);
+    _jimage = NULL;
+  }
+}
+
 ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) :
   ClassPathEntry(),
   _jimage(jimage) {
@@ -614,6 +621,12 @@
 void ClassLoader::setup_module_search_path(const char* path, TRAPS) {
   update_module_path_entry_list(path, THREAD);
 }
+
+void ClassLoader::close_jrt_image() {
+  assert(ClassLoader::has_jrt_entry(), "Not applicable for exploded builds");
+  _jrt_entry->close_jimage();
+}
+
 #endif // INCLUDE_CDS
 
 // Construct the array of module/path pairs as specified to --patch-module
--- a/src/hotspot/share/classfile/classLoader.hpp	Tue Dec 11 19:55:27 2018 -0800
+++ b/src/hotspot/share/classfile/classLoader.hpp	Wed Dec 12 10:13:11 2018 +0530
@@ -55,6 +55,7 @@
   virtual bool is_jar_file() const = 0;
   virtual const char* name() const = 0;
   virtual JImageFile* jimage() const = 0;
+  virtual void close_jimage() = 0;
   // Constructor
   ClassPathEntry() : _next(NULL) {}
   // Attempt to locate file_name through this class path entry.
@@ -70,6 +71,7 @@
   bool is_jar_file() const { return false;  }
   const char* name() const { return _dir; }
   JImageFile* jimage() const { return NULL; }
+  void close_jimage() {}
   ClassPathDirEntry(const char* dir);
   virtual ~ClassPathDirEntry() {}
   ClassFileStream* open_stream(const char* name, TRAPS);
@@ -98,6 +100,7 @@
   bool is_jar_file() const { return true;  }
   const char* name() const { return _zip_name; }
   JImageFile* jimage() const { return NULL; }
+  void close_jimage() {}
   ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append);
   virtual ~ClassPathZipEntry();
   u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
@@ -117,6 +120,7 @@
   bool is_open() const { return _jimage != NULL; }
   const char* name() const { return _name == NULL ? "" : _name; }
   JImageFile* jimage() const { return _jimage; }
+  void close_jimage();
   ClassPathImageEntry(JImageFile* jimage, const char* name);
   virtual ~ClassPathImageEntry();
   ClassFileStream* open_stream(const char* name, TRAPS);
@@ -333,6 +337,7 @@
   // Modular java runtime image is present vs. a build with exploded modules
   static bool has_jrt_entry() { return (_jrt_entry != NULL); }
   static ClassPathEntry* get_jrt_entry() { return _jrt_entry; }
+  static void close_jrt_image();
 
   // Add a module's exploded directory to the boot loader's exploded module build list
   static void add_to_exploded_build_list(Symbol* module_name, TRAPS);
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java	Tue Dec 11 19:55:27 2018 -0800
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java	Wed Dec 12 10:13:11 2018 +0530
@@ -23,8 +23,8 @@
 
 /**
  * @test
- * @bug 8174994
- * @summary Test the clhsdb commands 'printmdo', 'printall' on a CDS enabled corefile.
+ * @bug 8174994 8200613
+ * @summary Test the clhsdb commands 'printmdo', 'printall', 'jstack' on a CDS enabled corefile.
  * @requires vm.cds
  * @requires vm.hasSA
  * @requires os.family != "windows"
@@ -156,7 +156,7 @@
                 throw new SkippedException("The CDS archive is not mapped");
             }
 
-            cmds = List.of("printmdo -a", "printall");
+            cmds = List.of("printmdo -a", "printall", "jstack -v");
 
             Map<String, List<String>> expStrMap = new HashMap<>();
             Map<String, List<String>> unExpStrMap = new HashMap<>();
@@ -182,6 +182,11 @@
                 "illegal code",
                 "Failure occurred at bci",
                 "No suitable match for type of address"));
+            expStrMap.put("jstack -v", List.of(
+                "Common-Cleaner",
+                "Method*"));
+            unExpStrMap.put("jstack -v", List.of(
+                "sun.jvm.hotspot.debugger.UnmappedAddressException"));
             test.runOnCore(TEST_CDS_CORE_FILE_NAME, cmds, expStrMap, unExpStrMap);
         } catch (SkippedException e) {
             throw e;