changeset 6694:0553e00f9404

6424123, PR3702: JVM crashes on failed 'strdup' call Summary: Calling os::malloc()/os::strdup() and new os::strdup_check_oom() instead of ::malloc()/::strdup() for native memory tracking purpose Reviewed-by: coleenp, ctornqvi, kvn
author zgu
date Wed, 20 Feb 2019 02:15:29 +0000
parents ac58063ca713
children 62d0139577ca
files src/cpu/ppc/vm/vm_version_ppc.cpp src/cpu/sparc/vm/vm_version_sparc.cpp src/cpu/x86/vm/vm_version_x86.cpp src/os/aix/vm/os_aix.cpp src/os/aix/vm/porting_aix.cpp src/os/windows/vm/perfMemory_windows.cpp src/share/vm/c1/c1_LIRAssembler.cpp src/share/vm/classfile/classLoader.cpp src/share/vm/classfile/classLoader.hpp src/share/vm/compiler/compilerOracle.cpp src/share/vm/opto/runtime.cpp src/share/vm/opto/runtime.hpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/fprofiler.cpp src/share/vm/runtime/os.cpp src/share/vm/runtime/os.hpp src/share/vm/runtime/vmStructs.cpp src/share/vm/services/management.cpp src/share/vm/shark/sharkBuilder.cpp
diffstat 19 files changed, 65 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/ppc/vm/vm_version_ppc.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/cpu/ppc/vm/vm_version_ppc.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -28,6 +28,7 @@
 #include "macroAssembler_ppc.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/java.hpp"
+#include "runtime/os.hpp"
 #include "runtime/stubCodeGenerator.hpp"
 #include "utilities/defaultStream.hpp"
 #include "vm_version_ppc.hpp"
@@ -110,7 +111,7 @@
                (has_vand()    ? " vand"    : "")
                // Make sure number of %s matches num_features!
               );
-  _features_str = strdup(buf);
+  _features_str = os::strdup(buf);
   NOT_PRODUCT(if (Verbose) print_features(););
 
   // PPC64 supports 8-byte compare-exchange operations (see
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -26,6 +26,7 @@
 #include "assembler_sparc.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/java.hpp"
+#include "runtime/os.hpp"
 #include "runtime/stubCodeGenerator.hpp"
 #include "vm_version_sparc.hpp"
 #ifdef TARGET_OS_FAMILY_linux
@@ -261,7 +262,7 @@
                (!has_hardware_fsmuld() ? ", no-fsmuld" : ""));
 
   // buf is started with ", " or is empty
-  _features_str = strdup(strlen(buf) > 2 ? buf + 2 : buf);
+  _features_str = os::strdup(strlen(buf) > 2 ? buf + 2 : buf);
 
   // UseVIS is set to the smallest of what hardware supports and what
   // the command line requires.  I.e., you cannot set UseVIS to 3 on
--- a/src/cpu/x86/vm/vm_version_x86.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/cpu/x86/vm/vm_version_x86.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -26,6 +26,7 @@
 #include "assembler_x86.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/java.hpp"
+#include "runtime/os.hpp"
 #include "runtime/stubCodeGenerator.hpp"
 #include "vm_version_x86.hpp"
 #ifdef TARGET_OS_FAMILY_linux
@@ -454,7 +455,7 @@
                (supports_tsc() ? ", tsc": ""),
                (supports_tscinv_bit() ? ", tscinvbit": ""),
                (supports_tscinv() ? ", tscinv": ""));
-  _features_str = strdup(buf);
+  _features_str = os::strdup(buf);
 
   // UseSSE is set to the smaller of what hardware supports and what
   // the command line requires.  I.e., you cannot set UseSSE to 2 on
--- a/src/os/aix/vm/os_aix.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/os/aix/vm/os_aix.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -55,6 +55,7 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
+#include "runtime/os.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -388,9 +389,9 @@
   // default should be 4K.
   size_t data_page_size = SIZE_4K;
   {
-    void* p = ::malloc(SIZE_16M);
+    void* p = os::malloc(SIZE_16M, mtInternal);
     data_page_size = os::Aix::query_pagesize(p);
-    ::free(p);
+    os::free(p);
   }
 
   // query default shm page size (LDR_CNTRL SHMPSIZE)
--- a/src/os/aix/vm/porting_aix.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/os/aix/vm/porting_aix.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -22,6 +22,8 @@
  *
  */
 
+#include "memory/allocation.inline.hpp"
+#include "runtime/os.hpp"
 #include "loadlib_aix.hpp"
 #include "porting_aix.hpp"
 #include "utilities/debug.hpp"
@@ -84,7 +86,7 @@
     while (n) {
       node* p = n;
       n = n->next;
-      free(p->v);
+      os::free(p->v);
       delete p;
     }
   }
@@ -96,7 +98,7 @@
       }
     }
     node* p = new node;
-    p->v = strdup(s);
+    p->v = os::strdup_check_oom(s);
     p->next = first;
     first = p;
     return p->v;
--- a/src/os/windows/vm/perfMemory_windows.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/os/windows/vm/perfMemory_windows.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -29,6 +29,7 @@
 #include "oops/oop.inline.hpp"
 #include "os_windows.inline.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/os.hpp"
 #include "runtime/perfMemory.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/exceptions.hpp"
@@ -1388,7 +1389,7 @@
   // the file has been successfully created and the file mapping
   // object has been created.
   sharedmem_fileHandle = fh;
-  sharedmem_fileName = strdup(filename);
+  sharedmem_fileName = os::strdup(filename);
 
   return fmh;
 }
--- a/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -30,6 +30,7 @@
 #include "c1/c1_MacroAssembler.hpp"
 #include "c1/c1_ValueStack.hpp"
 #include "ci/ciInstance.hpp"
+#include "runtime/os.hpp"
 #ifdef TARGET_ARCH_x86
 # include "nativeInst_x86.hpp"
 # include "vmreg_x86.inline.hpp"
@@ -860,7 +861,7 @@
           stringStream st;
           st.print("bad oop %s at %d", r->as_Register()->name(), _masm->offset());
 #ifdef SPARC
-          _masm->_verify_oop(r->as_Register(), strdup(st.as_string()), __FILE__, __LINE__);
+          _masm->_verify_oop(r->as_Register(), os::strdup(st.as_string(), mtCompiler), __FILE__, __LINE__);
 #else
           _masm->verify_oop(r->as_Register());
 #endif
--- a/src/share/vm/classfile/classLoader.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/classfile/classLoader.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -288,13 +288,17 @@
 }
 
 LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st) : ClassPathEntry() {
-  _path = strdup(path);
+  _path = os::strdup_check_oom(path);
   _st = *st;
   _meta_index = NULL;
   _resolved_entry = NULL;
   _has_error = false;
 }
 
+LazyClassPathEntry::~LazyClassPathEntry() {
+  os::free((void*) _path);
+}
+
 bool LazyClassPathEntry::is_jar_file() {
   return ((_st.st_mode & S_IFREG) == S_IFREG);
 }
@@ -431,7 +435,7 @@
         default:
         {
           if (!skipCurrentJar && cur_entry != NULL) {
-            char* new_name = strdup(package_name);
+            char* new_name = os::strdup_check_oom(package_name);
             boot_class_path_packages.append(new_name);
           }
         }
--- a/src/share/vm/classfile/classLoader.hpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/classfile/classLoader.hpp	Wed Feb 20 02:15:29 2019 +0000
@@ -132,6 +132,8 @@
   bool is_jar_file();
   const char* name()  { return _path; }
   LazyClassPathEntry(char* path, const struct stat* st);
+  virtual ~LazyClassPathEntry();
+
   ClassFileStream* open_stream(const char* name, TRAPS);
   void set_meta_index(MetaIndex* meta_index) { _meta_index = meta_index; }
   virtual bool is_lazy();
--- a/src/share/vm/compiler/compilerOracle.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/compiler/compilerOracle.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -33,6 +33,7 @@
 #include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/jniHandles.hpp"
+#include "runtime/os.hpp"
 
 class MethodMatcher : public CHeapObj<mtCompiler> {
  public:
@@ -224,7 +225,7 @@
                            const T value,  MethodMatcher* next) :
     MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next),
                   _type(get_type_for<T>()), _value(copy_value<T>(value)) {
-    _option = strdup(opt);
+    _option = os::strdup_check_oom(opt);
   }
 
   ~TypedMethodOptionMatcher() {
--- a/src/share/vm/opto/runtime.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/opto/runtime.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -1331,9 +1331,9 @@
   }
   NamedCounter* c;
   if (tag == NamedCounter::BiasedLockingCounter) {
-    c = new BiasedLockingNamedCounter(strdup(st.as_string()));
+    c = new BiasedLockingNamedCounter(st.as_string());
   } else {
-    c = new NamedCounter(strdup(st.as_string()), tag);
+    c = new NamedCounter(st.as_string(), tag);
   }
 
   // atomically add the new counter to the head of the list.  We only
--- a/src/share/vm/opto/runtime.hpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/opto/runtime.hpp	Wed Feb 20 02:15:29 2019 +0000
@@ -72,11 +72,17 @@
 
  public:
   NamedCounter(const char *n, CounterTag tag = NoTag):
-    _name(n),
+    _name(n == NULL ? NULL : os::strdup(n)),
     _count(0),
     _next(NULL),
     _tag(tag) {}
 
+  ~NamedCounter() {
+    if (_name != NULL) {
+      os::free((void*)_name);
+    }
+  }
+
   const char * name() const     { return _name; }
   int count() const             { return _count; }
   address addr()                { return (address)&_count; }
--- a/src/share/vm/runtime/arguments.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/runtime/arguments.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -792,7 +792,7 @@
   } else {
     *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, *count, mtInternal);
   }
-  (*bldarray)[index] = strdup(arg);
+  (*bldarray)[index] = os::strdup_check_oom(arg);
 }
 
 void Arguments::build_jvm_args(const char* arg) {
@@ -1810,7 +1810,7 @@
 }
 
 void Arguments::process_java_launcher_argument(const char* launcher, void* extra_info) {
-  _sun_java_launcher = strdup(launcher);
+  _sun_java_launcher = os::strdup_check_oom(launcher);
   if (strcmp("gamma", _sun_java_launcher) == 0) {
     _created_by_gamma_launcher = true;
   }
@@ -2703,7 +2703,7 @@
       // Redirect GC output to the file. -Xloggc:<filename>
       // ostream_init_log(), when called will use this filename
       // to initialize a fileStream.
-      _gc_log_filename = strdup(tail);
+      _gc_log_filename = os::strdup_check_oom(tail);
      if (!is_filename_valid(_gc_log_filename)) {
        jio_fprintf(defaultStream::output_stream(),
                   "Invalid file name for use with -Xloggc: Filename can only contain the "
--- a/src/share/vm/runtime/fprofiler.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/runtime/fprofiler.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -618,10 +618,16 @@
   }
 
   vmNode(const char* name, const TickPosition where) : ProfilerNode() {
-    _name = name;
+    _name = os::strdup(name);
     update(where);
   }
 
+  ~vmNode() {
+    if (_name != NULL) {
+      os::free((void*)_name);
+    }
+  }
+
   const char *name()    const { return _name; }
   bool is_compiled()    const { return true; }
 
@@ -773,7 +779,7 @@
   assert(index >= 0, "Must be positive");
   // Note that we call strdup below since the symbol may be resource allocated
   if (!table[index]) {
-    table[index] = new (this) vmNode(os::strdup(name), where);
+    table[index] = new (this) vmNode(name, where);
   } else {
     ProfilerNode* prev = table[index];
     for(ProfilerNode* node = prev; node; node = node->next()) {
@@ -783,7 +789,7 @@
       }
       prev = node;
     }
-    prev->set_next(new (this) vmNode(os::strdup(name), where));
+    prev->set_next(new (this) vmNode(name, where));
   }
 }
 
--- a/src/share/vm/runtime/os.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/runtime/os.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -454,6 +454,13 @@
 }
 
 
+char* os::strdup_check_oom(const char* str, MEMFLAGS flags) {
+  char* p = os::strdup(str, flags);
+  if (p == NULL) {
+    vm_exit_out_of_memory(strlen(str) + 1, OOM_MALLOC_ERROR, "os::strdup_check_oom");
+  }
+  return p;
+}
 
 #ifdef ASSERT
 #define space_before             (MallocCushion + sizeof(double))
@@ -544,7 +551,6 @@
   }
 }
 
-
 void report_heap_error(void* memblock, void* bad, const char* where) {
   tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees);
   tty->print_cr("## memory stomp: byte at " PTR_FORMAT " %s object " PTR_FORMAT, bad, where, memblock);
--- a/src/share/vm/runtime/os.hpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/runtime/os.hpp	Wed Feb 20 02:15:29 2019 +0000
@@ -650,6 +650,8 @@
   static void  free    (void *memblock, MEMFLAGS flags = mtNone);
   static bool  check_heap(bool force = false);      // verify C heap integrity
   static char* strdup(const char *, MEMFLAGS flags = mtInternal);  // Like strdup
+  // Like strdup, but exit VM when strdup() returns NULL
+  static char* strdup_check_oom(const char*, MEMFLAGS flags = mtInternal);
 
 #ifndef PRODUCT
   static julong num_mallocs;         // # of calls to malloc/realloc
--- a/src/share/vm/runtime/vmStructs.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/runtime/vmStructs.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -51,6 +51,7 @@
 #include "interpreter/bytecodeInterpreter.hpp"
 #include "interpreter/bytecodes.hpp"
 #include "interpreter/interpreter.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/cardTableRS.hpp"
 #include "memory/compactPermGen.hpp"
 #include "memory/defNewGeneration.hpp"
@@ -102,6 +103,7 @@
 #include "runtime/globals.hpp"
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
+#include "runtime/os.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/serviceThread.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -3226,14 +3228,14 @@
     }
   }
   if (strstr(typeName, " const") == typeName + len - 6) {
-    char * s = strdup(typeName);
+    char * s = os::strdup_check_oom(typeName);
     s[len - 6] = '\0';
     // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName);
     if (recursiveFindType(origtypes, s, true) == 1) {
-      free(s);
+      os::free(s);
       return 1;
     }
-    free(s);
+    os::free(s);
   }
   if (!isRecurse) {
     tty->print_cr("type \"%s\" not found", typeName);
--- a/src/share/vm/services/management.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/services/management.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -1876,7 +1876,7 @@
   ResourceMark rm(THREAD); // thread->name() uses ResourceArea
 
   assert(thread->name() != NULL, "All threads should have a name");
-  _names_chars[_count] = strdup(thread->name());
+  _names_chars[_count] = os::strdup(thread->name());
   _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
                         os::thread_cpu_time(thread) : -1);
   _count++;
@@ -1894,7 +1894,7 @@
 
 ThreadTimesClosure::~ThreadTimesClosure() {
   for (int i = 0; i < _count; i++) {
-    free(_names_chars[i]);
+    os::free(_names_chars[i]);
   }
   FREE_C_HEAP_ARRAY(char *, _names_chars, mtInternal);
 }
--- a/src/share/vm/shark/sharkBuilder.cpp	Wed Feb 20 01:05:45 2019 +0000
+++ b/src/share/vm/shark/sharkBuilder.cpp	Wed Feb 20 02:15:29 2019 +0000
@@ -503,7 +503,7 @@
   const char *name;
   if (value->hasName())
     // XXX this leaks, but it's only debug code
-    name = strdup(value->getName().str().c_str());
+    name = os::strdup(value->getName().str().c_str());
   else
     name = "unnamed_value";