changeset 6856:5217fa82f1a4

6424123: 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 Mon, 11 Aug 2014 10:18:09 -0700
parents 0c7f758c15eb
children 4750cc1f4306 72030160367a 91f25b8a47af
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/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.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 20 files changed, 82 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/ppc/vm/vm_version_ppc.cpp	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/cpu/ppc/vm/vm_version_ppc.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -29,6 +29,7 @@
 #include "compiler/disassembler.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"
@@ -108,7 +109,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -26,6 +26,7 @@
 #include "asm/macroAssembler.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/java.hpp"
+#include "runtime/os.hpp"
 #include "runtime/stubCodeGenerator.hpp"
 #include "vm_version_sparc.hpp"
 
@@ -249,7 +250,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);
 
   // There are three 64-bit SPARC families that do not overlap, e.g.,
   // both is_ultra3() and is_sparc64() cannot be true at the same time.
--- a/src/cpu/x86/vm/vm_version_x86.cpp	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/cpu/x86/vm/vm_version_x86.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -27,6 +27,7 @@
 #include "asm/macroAssembler.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/java.hpp"
+#include "runtime/os.hpp"
 #include "runtime/stubCodeGenerator.hpp"
 #include "vm_version_x86.hpp"
 
@@ -514,7 +515,7 @@
                (supports_tscinv() ? ", tscinv": ""),
                (supports_bmi1() ? ", bmi1" : ""),
                (supports_bmi2() ? ", bmi2" : ""));
-  _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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/os/aix/vm/os_aix.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -58,6 +58,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
 #include "runtime/orderAccess.inline.hpp"
+#include "runtime/os.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -378,10 +379,10 @@
   // default should be 4K.
   size_t data_page_size = SIZE_4K;
   {
-    void* p = ::malloc(SIZE_16M);
+    void* p = os::malloc(SIZE_16M, mtInternal);
     guarantee(p != NULL, "malloc failed");
     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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/os/aix/vm/porting_aix.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -24,6 +24,8 @@
 
 #include "asm/assembler.hpp"
 #include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/os.hpp"
 #include "loadlib_aix.hpp"
 #include "porting_aix.hpp"
 #include "utilities/debug.hpp"
@@ -83,7 +85,7 @@
     while (n) {
       node* p = n;
       n = n->next;
-      free(p->v);
+      os::free(p->v);
       delete p;
     }
   }
@@ -95,7 +97,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/os/windows/vm/perfMemory_windows.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -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/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -23,6 +23,8 @@
  */
 
 #include "precompiled.hpp"
+#include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_sparc.hpp"
 
@@ -48,7 +50,7 @@
   // All SI defines used below must be supported.
   guarantee(bufsize != -1, "must be supported");
 
-  char* buf = (char*) malloc(bufsize);
+  char* buf = (char*) os::malloc(bufsize, mtInternal);
 
   if (buf == NULL)
     return;
@@ -60,7 +62,7 @@
     }
   }
 
-  free(buf);
+  os::free(buf);
 }
 
 int VM_Version::platform_features(int features) {
@@ -161,7 +163,7 @@
 
     char   tmp;
     size_t bufsize = sysinfo(SI_ISALIST, &tmp, 1);
-    char*  buf     = (char*) malloc(bufsize);
+    char*  buf     = (char*) os::malloc(bufsize, mtInternal);
 
     if (buf != NULL) {
       if (sysinfo(SI_ISALIST, buf, bufsize) == bufsize) {
@@ -184,7 +186,7 @@
           if (vis[3] == '2')                     features |= vis2_instructions_m;
         }
       }
-      free(buf);
+      os::free(buf);
     }
   }
 
@@ -228,7 +230,7 @@
             }
 #endif
             // Convert to UPPER case before compare.
-            char* impl = strdup(implementation);
+            char* impl = os::strdup_check_oom(implementation);
 
             for (int i = 0; impl[i] != 0; i++)
               impl[i] = (char)toupper((uint)impl[i]);
@@ -252,7 +254,7 @@
                 implementation = "SPARC";
               }
             }
-            free((void*)impl);
+            os::free((void*)impl);
             break;
           }
         } // for(
--- a/src/share/vm/c1/c1_LIRAssembler.cpp	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/c1/c1_LIRAssembler.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -30,6 +30,7 @@
 #include "c1/c1_MacroAssembler.hpp"
 #include "c1/c1_ValueStack.hpp"
 #include "ci/ciInstance.hpp"
+#include "runtime/os.hpp"
 
 void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
   // we must have enough patching space so that call can be inserted
@@ -848,7 +849,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/classfile/classLoader.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -273,13 +273,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(_path);
+}
+
 bool LazyClassPathEntry::is_jar_file() {
   return ((_st.st_mode & S_IFREG) == S_IFREG);
 }
@@ -416,7 +420,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);
           }
         }
@@ -438,7 +442,7 @@
 
 void ClassLoader::setup_bootstrap_search_path() {
   assert(_first_entry == NULL, "should not setup bootstrap class search path twice");
-  char* sys_class_path = os::strdup(Arguments::get_sysclasspath());
+  char* sys_class_path = os::strdup_check_oom(Arguments::get_sysclasspath());
   if (TraceClassLoading && Verbose) {
     tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path);
   }
@@ -460,6 +464,7 @@
       end++;
     }
   }
+  os::free(sys_class_path);
 }
 
 ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, bool lazy, TRAPS) {
--- a/src/share/vm/classfile/classLoader.hpp	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/classfile/classLoader.hpp	Mon Aug 11 10:18:09 2014 -0700
@@ -128,6 +128,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/compiler/compilerOracle.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -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:
@@ -175,7 +176,11 @@
                              Symbol* method_name, Mode method_mode,
                              Symbol* signature, const char * opt, MethodMatcher* next):
     MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) {
-    option = opt;
+    option = os::strdup_check_oom(opt);
+  }
+
+  virtual ~MethodOptionMatcher() {
+    os::free((void*)option);
   }
 
   bool match(methodHandle method, const char* opt) {
@@ -498,7 +503,7 @@
           tty->print("CompilerOracle: %s ", command_names[command]);
           match->print();
         }
-        match = add_option_string(c_name, c_match, m_name, m_match, signature, strdup(option));
+        match = add_option_string(c_name, c_match, m_name, m_match, signature, option);
         line += bytes_read;
       }
     } else {
--- a/src/share/vm/opto/runtime.cpp	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/opto/runtime.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -1381,11 +1381,11 @@
   }
   NamedCounter* c;
   if (tag == NamedCounter::BiasedLockingCounter) {
-    c = new BiasedLockingNamedCounter(strdup(st.as_string()));
+    c = new BiasedLockingNamedCounter(st.as_string());
   } else if (tag == NamedCounter::RTMLockingCounter) {
-    c = new RTMLockingNamedCounter(strdup(st.as_string()));
+    c = new RTMLockingNamedCounter(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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/opto/runtime.hpp	Mon Aug 11 10:18:09 2014 -0700
@@ -75,11 +75,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/runtime/arguments.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -800,7 +800,7 @@
   } else {
     *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, new_count, mtInternal);
   }
-  (*bldarray)[*count] = strdup(arg);
+  (*bldarray)[*count] = os::strdup_check_oom(arg);
   *count = new_count;
 }
 
@@ -1886,7 +1886,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);
 }
 
 bool Arguments::created_by_java_launcher() {
@@ -2996,7 +2996,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/runtime/fprofiler.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -629,10 +629,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; }
 
@@ -784,7 +790,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()) {
@@ -794,7 +800,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/runtime/os.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -517,6 +517,14 @@
   return dup_str;
 }
 
+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;
+}
+
 
 #define paranoid                 0  /* only set to 1 if you suspect checking code has bug */
 
--- a/src/share/vm/runtime/os.hpp	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/runtime/os.hpp	Mon Aug 11 10:18:09 2014 -0700
@@ -664,6 +664,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/runtime/vmStructs.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -52,6 +52,7 @@
 #include "interpreter/bytecodes.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/cardTableRS.hpp"
 #include "memory/defNewGeneration.hpp"
 #include "memory/freeBlockDictionary.hpp"
@@ -93,6 +94,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"
@@ -3296,14 +3298,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/services/management.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -1914,7 +1914,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++;
@@ -1932,7 +1932,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	Mon Aug 11 07:30:46 2014 -0700
+++ b/src/share/vm/shark/sharkBuilder.cpp	Mon Aug 11 10:18:09 2014 -0700
@@ -413,7 +413,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";