--- old/src/os/bsd/vm/os_bsd.cpp 2013-03-13 09:05:04.708389597 +0100 +++ new/src/os/bsd/vm/os_bsd.cpp 2013-03-13 09:05:04.548389604 +0100 @@ -166,18 +166,38 @@ return Bsd::physical_memory(); } -julong os::allocatable_physical_memory(julong size) { +bool os::has_allocatable_memory_limit(julong& limit) { + struct rlimit rlim; + // RLIMIT_AS is the same as RLIMIT_VMEM on this platform + int getrlimit_res = getrlimit(RLIMIT_AS, &rlim); + // if there was an error when calling getrlimit, assume that there is no limitation + // on virtual memory. + bool result; + if ((getrlimit_res != 0) || (rlim.rlim_cur == RLIM_INFINITY)) { + result = false; + } else { + limit = (julong)rlim.rlim_cur; + result = true; + } #ifdef _LP64 - return size; + return result; #else - julong result = MIN2(size, (julong)3800*M); - if (!is_allocatable(result)) { - // See comments under solaris for alignment considerations - julong reasonable_size = (julong)2*G - 2 * os::vm_page_size(); - result = MIN2(size, reasonable_size); - } - return result; -#endif // _LP64 + // arbitrary virtual space limit for BSD found by testing. If getrlimit + // above returned a limit, bound it with this limit. Otherwise directly use + // it as limit. + const julong max_virtual_limit = (julong)3800*M; + if (result) { + limit = MIN2(limit, max_virtual_limit); + } else { + limit = max_virtual_limit; + } + if (!is_allocatable(limit)) { + // See comments under solaris for alignment considerations + julong reasonable_limit = (julong)2*G - 2 * os::vm_page_size(); + limit = MIN2(size, reasonable_limit); + } + return true; +#endif } //////////////////////////////////////////////////////////////////////////////// --- old/src/os/linux/vm/os_linux.cpp 2013-03-13 09:05:05.644389561 +0100 +++ new/src/os/linux/vm/os_linux.cpp 2013-03-13 09:05:05.416389571 +0100 @@ -191,18 +191,37 @@ return Linux::physical_memory(); } -julong os::allocatable_physical_memory(julong size) { +bool os::has_allocatable_memory_limit(julong& limit) { + struct rlimit rlim; + int getrlimit_res = getrlimit(RLIMIT_AS, &rlim); + // if there was an error when calling getrlimit, assume that there is no limitation + // on virtual memory. + bool result; + if ((getrlimit_res != 0) || (rlim.rlim_cur == RLIM_INFINITY)) { + result = false; + } else { + limit = (julong)rlim.rlim_cur; + result = true; + } #ifdef _LP64 - return size; + return result; #else - julong result = MIN2(size, (julong)3800*M); - if (!is_allocatable(result)) { - // See comments under solaris for alignment considerations - julong reasonable_size = (julong)2*G - 2 * os::vm_page_size(); - result = MIN2(size, reasonable_size); - } - return result; -#endif // _LP64 + // arbitrary virtual space limit for Linux found by testing. If getrlimit + // above returned a limit, bound it with this limit. Otherwise directly use + // it as limit. + const julong max_virtual_limit = (julong)3800*M; + if (result) { + limit = MIN2(limit, max_virtual_limit); + } else { + limit = max_virtual_limit; + } + if (!is_allocatable(limit)) { + // See comments under solaris for alignment considerations + julong reasonable_limit = (julong)2*G - 2 * os::vm_page_size(); + limit = MIN2(limit, reasonable_limit); + } + return true; +#endif } //////////////////////////////////////////////////////////////////////////////// @@ -1142,7 +1161,7 @@ struct rlimit rlim; getrlimit(RLIMIT_STACK, &rlim); stack_size = rlim.rlim_cur; - + // 6308388: a bug in ld.so will relocate its own .data section to the // lower end of primordial stack; reduce ulimit -s value a little bit // so we won't install guard page on ld.so's data section. --- old/src/os/solaris/vm/os_solaris.cpp 2013-03-13 09:05:06.548389527 +0100 +++ new/src/os/solaris/vm/os_solaris.cpp 2013-03-13 09:05:06.412389532 +0100 @@ -476,21 +476,41 @@ return Solaris::physical_memory(); } -julong os::allocatable_physical_memory(julong size) { +bool os::has_allocatable_memory_limit(julong& limit) { + struct rlimit rlim; + // Solaris defines RLIMIT_AS as RLIMIT_VMEM. + int getrlimit_res = getrlimit(RLIMIT_AS, &rlim); + // if there was an error when calling getrlimit, assume that there is no limitation + // on virtual memory. + bool result; + if ((getrlimit_res != 0) || (rlim.rlim_cur == RLIM_INFINITY)) { + result = false; + } else { + limit = (julong)rlim.rlim_cur; + result = true; + } #ifdef _LP64 - return size; + return result; #else - julong result = MIN2(size, (julong)3835*M); - if (!is_allocatable(result)) { - // Memory allocations will be aligned but the alignment - // is not known at this point. Alignments will - // be at most to LargePageSizeInBytes. Protect - // allocations from alignments up to illegal - // values. If at this point 2G is illegal. - julong reasonable_size = (julong)2*G - 2 * LargePageSizeInBytes; - result = MIN2(size, reasonable_size); - } - return result; + // arbitrary virtual space limit for Solaris found by testing. If getrlimit + // above returned a limit, bound it with this limit. Otherwise directly use + // it as limit. + const julong max_virtual_limit = (julong)3835*M; + if (result) { + limit = MIN2(limit, max_virtual_limit); + } else { + limit = max_virtual_limit; + } + if (!is_allocatable(limit)) { + // Memory allocations will be aligned but the alignment + // is not known at this point. Alignments will + // be at most to LargePageSizeInBytes. Protect + // allocations from alignments up to illegal + // values. If at this point 2G is illegal. + julong reasonable_limit = (julong)2*G - 2 * LargePageSizeInBytes; + limit = MIN2(limit, reasonable_limit); + } + return true; #endif } --- old/src/os/windows/vm/os_windows.cpp 2013-03-13 09:05:08.284389462 +0100 +++ new/src/os/windows/vm/os_windows.cpp 2013-03-13 09:05:08.148389468 +0100 @@ -685,12 +685,17 @@ return win32::physical_memory(); } -julong os::allocatable_physical_memory(julong size) { +bool os::has_allocatable_memory_limit(julong& limit) { + MEMORYSTATUSEX ms; + ms.dwLength = sizeof(ms); + GlobalMemoryStatusEx(&ms); #ifdef _LP64 - return size; + limit = (julong)ms.ullAvailVirtual; + return true; #else // Limit to 1400m because of the 2gb address space wall - return MIN2(size, (julong)1400*M); + limit = MIN2((julong)1400*M, (julong)ms.ullAvailVirtual); + return true; #endif } --- old/src/share/vm/runtime/arguments.cpp 2013-03-13 09:05:09.140389429 +0100 +++ new/src/share/vm/runtime/arguments.cpp 2013-03-13 09:05:08.988389436 +0100 @@ -1546,6 +1546,15 @@ } } +julong Arguments::allocatable_physical_memory(julong limit) { + julong max_allocatable; + julong result = limit; + if (os::has_allocatable_memory_limit(max_allocatable)) { + result = MIN2(result, max_allocatable / MaxVirtMemFraction); + } + return result; +} + void Arguments::set_heap_size() { if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) { // Deprecated flag @@ -1561,7 +1570,7 @@ // respecting the maximum and minimum sizes of the heap. if (FLAG_IS_DEFAULT(MaxHeapSize)) { julong reasonable_max = phys_mem / MaxRAMFraction; - + if (phys_mem <= MaxHeapSize * MinRAMFraction) { // Small physical memory, so use a minimum fraction of it for the heap reasonable_max = phys_mem / MinRAMFraction; @@ -1584,7 +1593,7 @@ } reasonable_max = MIN2(reasonable_max, max_coop_heap); } - reasonable_max = os::allocatable_physical_memory(reasonable_max); + reasonable_max = allocatable_physical_memory(reasonable_max); if (!FLAG_IS_DEFAULT(InitialHeapSize)) { // An initial heap size was specified on the command line, @@ -1609,14 +1618,14 @@ reasonable_minimum = MIN2(reasonable_minimum, (julong)MaxHeapSize); - reasonable_minimum = os::allocatable_physical_memory(reasonable_minimum); + reasonable_minimum = allocatable_physical_memory(reasonable_minimum); julong reasonable_initial = phys_mem / InitialRAMFraction; reasonable_initial = MAX2(reasonable_initial, reasonable_minimum); reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize); - reasonable_initial = os::allocatable_physical_memory(reasonable_initial); + reasonable_initial = allocatable_physical_memory(reasonable_initial); if (PrintGCDetails && Verbose) { // Cannot use gclog_or_tty yet. @@ -2597,7 +2606,7 @@ // Make sure that if we have a lot of memory we cap the 32 bit // process space. The 64bit VM version of this function is a nop. - initHeapSize = os::allocatable_physical_memory(initHeapSize); + initHeapSize = allocatable_physical_memory(initHeapSize); if (FLAG_IS_DEFAULT(MaxHeapSize)) { FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize); --- old/src/share/vm/runtime/arguments.hpp 2013-03-13 09:05:09.980389398 +0100 +++ new/src/share/vm/runtime/arguments.hpp 2013-03-13 09:05:09.812389405 +0100 @@ -311,6 +311,9 @@ // GC ergonomics static void set_ergonomics_flags(); static void set_shared_spaces_flags(); + // limits the given size by the maximum amount of memory this process is + // currently allowed to allocate or reserve. + static julong allocatable_physical_memory(julong limit); // Setup heap size static void set_heap_size(); // Based on automatic selection criteria, should the --- old/src/share/vm/runtime/globals.hpp 2013-03-13 09:05:10.796389368 +0100 +++ new/src/share/vm/runtime/globals.hpp 2013-03-13 09:05:10.648389373 +0100 @@ -1958,6 +1958,9 @@ product(uintx, InitialRAMFraction, 64, \ "Fraction (1/n) of real memory used for initial heap size") \ \ + product(uintx, MaxVirtMemFraction, 2, \ + "Fraction (1/n) of virtual memory used for heap size") \ + \ product(bool, UseAutoGCSelectPolicy, false, \ "Use automatic collection selection policy") \ \ --- old/src/share/vm/runtime/os.hpp 2013-03-13 09:05:11.752389332 +0100 +++ new/src/share/vm/runtime/os.hpp 2013-03-13 09:05:11.536389340 +0100 @@ -184,7 +184,7 @@ } static julong available_memory(); static julong physical_memory(); - static julong allocatable_physical_memory(julong size); + static bool has_allocatable_memory_limit(julong& limit); static bool is_server_class_machine(); // number of CPUs