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
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/os/aix/vm/os_aix.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/os/aix/vm/porting_aix.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/os/windows/vm/perfMemory_windows.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/classfile/classLoader.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/classfile/classLoader.hpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/compiler/compilerOracle.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/opto/runtime.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/opto/runtime.hpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/runtime/arguments.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/runtime/fprofiler.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/runtime/os.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/runtime/os.hpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/services/management.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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/hotspot/src/share/vm/shark/sharkBuilder.cpp Mon Aug 11 07:30:46 2014 -0700
+++ b/hotspot/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";