提交 161b31ec 编写于 作者: D dcubed

Merge

...@@ -1811,13 +1811,15 @@ bool os::Linux::_stack_is_executable = false; ...@@ -1811,13 +1811,15 @@ bool os::Linux::_stack_is_executable = false;
class VM_LinuxDllLoad: public VM_Operation { class VM_LinuxDllLoad: public VM_Operation {
private: private:
const char *_filename; const char *_filename;
char *_ebuf;
int _ebuflen;
void *_lib; void *_lib;
public: public:
VM_LinuxDllLoad(const char *fn) : VM_LinuxDllLoad(const char *fn, char *ebuf, int ebuflen) :
_filename(fn), _lib(NULL) {} _filename(fn), _ebuf(ebuf), _ebuflen(ebuflen), _lib(NULL) {}
VMOp_Type type() const { return VMOp_LinuxDllLoad; } VMOp_Type type() const { return VMOp_LinuxDllLoad; }
void doit() { void doit() {
_lib = os::Linux::dll_load_inner(_filename); _lib = os::Linux::dll_load_in_vmthread(_filename, _ebuf, _ebuflen);
os::Linux::_stack_is_executable = true; os::Linux::_stack_is_executable = true;
} }
void* loaded_library() { return _lib; } void* loaded_library() { return _lib; }
...@@ -1865,13 +1867,13 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) ...@@ -1865,13 +1867,13 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
// This is for the case where the DLL has an static // This is for the case where the DLL has an static
// constructor function that executes JNI code. We cannot // constructor function that executes JNI code. We cannot
// load such DLLs in the VMThread. // load such DLLs in the VMThread.
result = ::dlopen(filename, RTLD_LAZY); result = os::Linux::dlopen_helper(filename, ebuf, ebuflen);
} }
ThreadInVMfromNative tiv(jt); ThreadInVMfromNative tiv(jt);
debug_only(VMNativeEntryWrapper vew;) debug_only(VMNativeEntryWrapper vew;)
VM_LinuxDllLoad op(filename); VM_LinuxDllLoad op(filename, ebuf, ebuflen);
VMThread::execute(&op); VMThread::execute(&op);
if (LoadExecStackDllInVMThread) { if (LoadExecStackDllInVMThread) {
result = op.loaded_library(); result = op.loaded_library();
...@@ -1883,7 +1885,7 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) ...@@ -1883,7 +1885,7 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
} }
if (!load_attempted) { if (!load_attempted) {
result = ::dlopen(filename, RTLD_LAZY); result = os::Linux::dlopen_helper(filename, ebuf, ebuflen);
} }
if (result != NULL) { if (result != NULL) {
...@@ -1892,11 +1894,6 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) ...@@ -1892,11 +1894,6 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
} }
Elf32_Ehdr elf_head; Elf32_Ehdr elf_head;
// Read system error message into ebuf
// It may or may not be overwritten below
::strncpy(ebuf, ::dlerror(), ebuflen-1);
ebuf[ebuflen-1]='\0';
int diag_msg_max_length=ebuflen-strlen(ebuf); int diag_msg_max_length=ebuflen-strlen(ebuf);
char* diag_msg_buf=ebuf+strlen(ebuf); char* diag_msg_buf=ebuf+strlen(ebuf);
...@@ -2039,10 +2036,19 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) ...@@ -2039,10 +2036,19 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
return NULL; return NULL;
} }
void * os::Linux::dll_load_inner(const char *filename) { void * os::Linux::dlopen_helper(const char *filename, char *ebuf, int ebuflen) {
void * result = ::dlopen(filename, RTLD_LAZY);
if (result == NULL) {
::strncpy(ebuf, ::dlerror(), ebuflen - 1);
ebuf[ebuflen-1] = '\0';
}
return result;
}
void * os::Linux::dll_load_in_vmthread(const char *filename, char *ebuf, int ebuflen) {
void * result = NULL; void * result = NULL;
if (LoadExecStackDllInVMThread) { if (LoadExecStackDllInVMThread) {
result = ::dlopen(filename, RTLD_LAZY); result = dlopen_helper(filename, ebuf, ebuflen);
} }
// Since 7019808, libjvm.so is linked with -noexecstack. If the VM loads a // Since 7019808, libjvm.so is linked with -noexecstack. If the VM loads a
......
...@@ -95,7 +95,8 @@ class Linux { ...@@ -95,7 +95,8 @@ class Linux {
public: public:
static bool _stack_is_executable; static bool _stack_is_executable;
static void *dll_load_inner(const char *name); static void *dlopen_helper(const char *name, char *ebuf, int ebuflen);
static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen);
static void init_thread_fpu_state(); static void init_thread_fpu_state();
static int get_fpu_control_word(); static int get_fpu_control_word();
......
...@@ -46,7 +46,7 @@ define_pd_global(uintx, SurvivorRatio, 8); ...@@ -46,7 +46,7 @@ define_pd_global(uintx, SurvivorRatio, 8);
define_pd_global(uintx, JVMInvokeMethodSlack, 8192); define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
// Used on 64 bit platforms for UseCompressedOops base address or CDS // Used on 64 bit platforms for UseCompressedOops base address
define_pd_global(uintx, HeapBaseMinAddress, 2*G); define_pd_global(uintx, HeapBaseMinAddress, 2*G);
#endif // OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP #endif // OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP
...@@ -41,7 +41,7 @@ define_pd_global(intx, VMThreadStackSize, 512); ...@@ -41,7 +41,7 @@ define_pd_global(intx, VMThreadStackSize, 512);
define_pd_global(intx, CompilerThreadStackSize, 0); define_pd_global(intx, CompilerThreadStackSize, 0);
define_pd_global(uintx, JVMInvokeMethodSlack, 8192); define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
// Used on 64 bit platforms for UseCompressedOops base address or CDS // Used on 64 bit platforms for UseCompressedOops base address
define_pd_global(uintx, HeapBaseMinAddress, 2*G); define_pd_global(uintx, HeapBaseMinAddress, 2*G);
#endif // OS_CPU_BSD_ZERO_VM_GLOBALS_BSD_ZERO_HPP #endif // OS_CPU_BSD_ZERO_VM_GLOBALS_BSD_ZERO_HPP
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
define_pd_global(uintx, JVMInvokeMethodSlack, 12288); define_pd_global(uintx, JVMInvokeMethodSlack, 12288);
define_pd_global(intx, CompilerThreadStackSize, 0); define_pd_global(intx, CompilerThreadStackSize, 0);
// Used on 64 bit platforms for UseCompressedOops base address or CDS // Used on 64 bit platforms for UseCompressedOops base address
define_pd_global(uintx, HeapBaseMinAddress, CONST64(4)*G); define_pd_global(uintx, HeapBaseMinAddress, CONST64(4)*G);
#endif // OS_CPU_LINUX_SPARC_VM_GLOBALS_LINUX_SPARC_HPP #endif // OS_CPU_LINUX_SPARC_VM_GLOBALS_LINUX_SPARC_HPP
...@@ -44,7 +44,7 @@ define_pd_global(intx, CompilerThreadStackSize, 0); ...@@ -44,7 +44,7 @@ define_pd_global(intx, CompilerThreadStackSize, 0);
define_pd_global(uintx,JVMInvokeMethodSlack, 8192); define_pd_global(uintx,JVMInvokeMethodSlack, 8192);
// Used on 64 bit platforms for UseCompressedOops base address or CDS // Used on 64 bit platforms for UseCompressedOops base address
define_pd_global(uintx,HeapBaseMinAddress, 2*G); define_pd_global(uintx,HeapBaseMinAddress, 2*G);
#endif // OS_CPU_LINUX_X86_VM_GLOBALS_LINUX_X86_HPP #endif // OS_CPU_LINUX_X86_VM_GLOBALS_LINUX_X86_HPP
...@@ -41,7 +41,7 @@ define_pd_global(intx, VMThreadStackSize, 512); ...@@ -41,7 +41,7 @@ define_pd_global(intx, VMThreadStackSize, 512);
define_pd_global(intx, CompilerThreadStackSize, 0); define_pd_global(intx, CompilerThreadStackSize, 0);
define_pd_global(uintx, JVMInvokeMethodSlack, 8192); define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
// Used on 64 bit platforms for UseCompressedOops base address or CDS // Used on 64 bit platforms for UseCompressedOops base address
define_pd_global(uintx, HeapBaseMinAddress, 2*G); define_pd_global(uintx, HeapBaseMinAddress, 2*G);
#endif // OS_CPU_LINUX_ZERO_VM_GLOBALS_LINUX_ZERO_HPP #endif // OS_CPU_LINUX_ZERO_VM_GLOBALS_LINUX_ZERO_HPP
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
define_pd_global(uintx, JVMInvokeMethodSlack, 12288); define_pd_global(uintx, JVMInvokeMethodSlack, 12288);
define_pd_global(intx, CompilerThreadStackSize, 0); define_pd_global(intx, CompilerThreadStackSize, 0);
// Used on 64 bit platforms for UseCompressedOops base address or CDS // Used on 64 bit platforms for UseCompressedOops base address
#ifdef _LP64 #ifdef _LP64
define_pd_global(uintx, HeapBaseMinAddress, CONST64(4)*G); define_pd_global(uintx, HeapBaseMinAddress, CONST64(4)*G);
#else #else
......
...@@ -43,7 +43,7 @@ define_pd_global(uintx,JVMInvokeMethodSlack, 10*K); ...@@ -43,7 +43,7 @@ define_pd_global(uintx,JVMInvokeMethodSlack, 10*K);
define_pd_global(intx, CompilerThreadStackSize, 0); define_pd_global(intx, CompilerThreadStackSize, 0);
// Used on 64 bit platforms for UseCompressedOops base address or CDS // Used on 64 bit platforms for UseCompressedOops base address
define_pd_global(uintx,HeapBaseMinAddress, 256*M); define_pd_global(uintx,HeapBaseMinAddress, 256*M);
#endif // OS_CPU_SOLARIS_X86_VM_GLOBALS_SOLARIS_X86_HPP #endif // OS_CPU_SOLARIS_X86_VM_GLOBALS_SOLARIS_X86_HPP
...@@ -45,7 +45,7 @@ define_pd_global(intx, CompilerThreadStackSize, 0); ...@@ -45,7 +45,7 @@ define_pd_global(intx, CompilerThreadStackSize, 0);
define_pd_global(uintx, JVMInvokeMethodSlack, 8192); define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
// Used on 64 bit platforms for UseCompressedOops base address or CDS // Used on 64 bit platforms for UseCompressedOops base address
define_pd_global(uintx, HeapBaseMinAddress, 2*G); define_pd_global(uintx, HeapBaseMinAddress, 2*G);
#endif // OS_CPU_WINDOWS_X86_VM_GLOBALS_WINDOWS_X86_HPP #endif // OS_CPU_WINDOWS_X86_VM_GLOBALS_WINDOWS_X86_HPP
...@@ -372,7 +372,7 @@ ReservedSpace FileMapInfo::reserve_shared_memory() { ...@@ -372,7 +372,7 @@ ReservedSpace FileMapInfo::reserve_shared_memory() {
// other reserved memory (like the code cache). // other reserved memory (like the code cache).
ReservedSpace rs(size, alignment, false, requested_addr); ReservedSpace rs(size, alignment, false, requested_addr);
if (!rs.is_reserved()) { if (!rs.is_reserved()) {
fail_continue(err_msg("Unable to reserved shared space at required address " INTPTR_FORMAT, requested_addr)); fail_continue(err_msg("Unable to reserve shared space at required address " INTPTR_FORMAT, requested_addr));
return rs; return rs;
} }
// the reserved virtual memory is for mapping class data sharing archive // the reserved virtual memory is for mapping class data sharing archive
......
...@@ -337,27 +337,16 @@ VirtualSpaceNode::VirtualSpaceNode(size_t byte_size) : _top(NULL), _next(NULL), ...@@ -337,27 +337,16 @@ VirtualSpaceNode::VirtualSpaceNode(size_t byte_size) : _top(NULL), _next(NULL),
// align up to vm allocation granularity // align up to vm allocation granularity
byte_size = align_size_up(byte_size, os::vm_allocation_granularity()); byte_size = align_size_up(byte_size, os::vm_allocation_granularity());
// This allocates memory with mmap. For DumpSharedspaces, allocate the // This allocates memory with mmap. For DumpSharedspaces, try to reserve
// space at low memory so that other shared images don't conflict. // configurable address, generally at the top of the Java heap so other
// This is the same address as memory needed for UseCompressedOops but // memory addresses don't conflict.
// compressed oops don't work with CDS (offsets in metadata are wrong), so
// borrow the same address.
if (DumpSharedSpaces) { if (DumpSharedSpaces) {
char* shared_base = (char*)HeapBaseMinAddress; char* shared_base = (char*)SharedBaseAddress;
_rs = ReservedSpace(byte_size, 0, false, shared_base, 0); _rs = ReservedSpace(byte_size, 0, false, shared_base, 0);
if (_rs.is_reserved()) { if (_rs.is_reserved()) {
assert(_rs.base() == shared_base, "should match"); assert(shared_base == 0 || _rs.base() == shared_base, "should match");
} else { } else {
// If we are dumping the heap, then allocate a wasted block of address // Get a mmap region anywhere if the SharedBaseAddress fails.
// space in order to push the heap to a lower address. This extra
// address range allows for other (or larger) libraries to be loaded
// without them occupying the space required for the shared spaces.
uintx reserved = 0;
uintx block_size = 64*1024*1024;
while (reserved < SharedDummyBlockSize) {
char* dummy = os::reserve_memory(block_size);
reserved += block_size;
}
_rs = ReservedSpace(byte_size); _rs = ReservedSpace(byte_size);
} }
MetaspaceShared::set_shared_rs(&_rs); MetaspaceShared::set_shared_rs(&_rs);
......
...@@ -1722,7 +1722,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, ...@@ -1722,7 +1722,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass,
int i; int i;
for (i = 0; i < methods_length; i++) { for (i = 0; i < methods_length; i++) {
methodHandle method(THREAD, methods->at(i)); methodHandle method(THREAD, methods->at(i));
if (!method->is_initializer()) { if (!method->is_initializer() && !method->is_overpass()) {
if (!publicOnly || method->is_public()) { if (!publicOnly || method->is_public()) {
++num_methods; ++num_methods;
} }
...@@ -1736,7 +1736,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, ...@@ -1736,7 +1736,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass,
int out_idx = 0; int out_idx = 0;
for (i = 0; i < methods_length; i++) { for (i = 0; i < methods_length; i++) {
methodHandle method(THREAD, methods->at(i)); methodHandle method(THREAD, methods->at(i));
if (!method->is_initializer()) { if (!method->is_initializer() && !method->is_overpass()) {
if (!publicOnly || method->is_public()) { if (!publicOnly || method->is_public()) {
oop m = Reflection::new_method(method, UseNewReflection, false, CHECK_NULL); oop m = Reflection::new_method(method, UseNewReflection, false, CHECK_NULL);
result->obj_at_put(out_idx, m); result->obj_at_put(out_idx, m);
......
...@@ -869,6 +869,11 @@ class CommandLineFlags { ...@@ -869,6 +869,11 @@ class CommandLineFlags {
diagnostic(bool, PrintNMTStatistics, false, \ diagnostic(bool, PrintNMTStatistics, false, \
"Print native memory tracking summary data if it is on") \ "Print native memory tracking summary data if it is on") \
\ \
diagnostic(bool, AutoShutdownNMT, true, \
"Automatically shutdown native memory tracking under stress " \
"situation. When set to false, native memory tracking tries to " \
"stay alive at the expense of JVM performance") \
\
diagnostic(bool, LogCompilation, false, \ diagnostic(bool, LogCompilation, false, \
"Log compilation activity in detail to hotspot.log or LogFile") \ "Log compilation activity in detail to hotspot.log or LogFile") \
\ \
...@@ -2905,6 +2910,10 @@ class CommandLineFlags { ...@@ -2905,6 +2910,10 @@ class CommandLineFlags {
"if non-zero, start verifying C heap after Nth call to " \ "if non-zero, start verifying C heap after Nth call to " \
"malloc/realloc/free") \ "malloc/realloc/free") \
\ \
diagnostic(uintx, MallocMaxTestWords, 0, \
"if non-zero, max # of Words that malloc/realloc can allocate " \
"(for testing only)") \
\
product(intx, TypeProfileWidth, 2, \ product(intx, TypeProfileWidth, 2, \
"number of receiver types to record in call/cast profile") \ "number of receiver types to record in call/cast profile") \
\ \
...@@ -3569,8 +3578,9 @@ class CommandLineFlags { ...@@ -3569,8 +3578,9 @@ class CommandLineFlags {
product(uintx, SharedMiscCodeSize, 120*K, \ product(uintx, SharedMiscCodeSize, 120*K, \
"Size of the shared miscellaneous code area (in bytes)") \ "Size of the shared miscellaneous code area (in bytes)") \
\ \
product(uintx, SharedDummyBlockSize, 0, \ product(uintx, SharedBaseAddress, LP64_ONLY(32*G) \
"Size of dummy block used to shift heap addresses (in bytes)") \ NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \
"Address to allocate shared memory region for class data") \
\ \
diagnostic(bool, EnableInvokeDynamic, true, \ diagnostic(bool, EnableInvokeDynamic, true, \
"support JSR 292 (method handles, invokedynamic, " \ "support JSR 292 (method handles, invokedynamic, " \
......
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -80,6 +80,8 @@ julong os::num_frees = 0; // # of calls to free ...@@ -80,6 +80,8 @@ julong os::num_frees = 0; // # of calls to free
julong os::free_bytes = 0; // # of bytes freed julong os::free_bytes = 0; // # of bytes freed
#endif #endif
static juint cur_malloc_words = 0; // current size for MallocMaxTestWords
void os_init_globals() { void os_init_globals() {
// Called from init_globals(). // Called from init_globals().
// See Threads::create_vm() in thread.cpp, and init.cpp. // See Threads::create_vm() in thread.cpp, and init.cpp.
...@@ -570,6 +572,26 @@ void verify_block(void* memblock) { ...@@ -570,6 +572,26 @@ void verify_block(void* memblock) {
} }
#endif #endif
//
// This function supports testing of the malloc out of memory
// condition without really running the system out of memory.
//
static u_char* testMalloc(size_t alloc_size) {
assert(MallocMaxTestWords > 0, "sanity check");
if ((cur_malloc_words + (alloc_size / BytesPerWord)) > MallocMaxTestWords) {
return NULL;
}
u_char* ptr = (u_char*)::malloc(alloc_size);
if (ptr != NULL) {
Atomic::add(((jint) (alloc_size / BytesPerWord)),
(volatile jint *) &cur_malloc_words);
}
return ptr;
}
void* os::malloc(size_t size, MEMFLAGS memflags, address caller) { void* os::malloc(size_t size, MEMFLAGS memflags, address caller) {
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
...@@ -579,11 +601,22 @@ void* os::malloc(size_t size, MEMFLAGS memflags, address caller) { ...@@ -579,11 +601,22 @@ void* os::malloc(size_t size, MEMFLAGS memflags, address caller) {
// if NULL is returned the calling functions assume out of memory. // if NULL is returned the calling functions assume out of memory.
size = 1; size = 1;
} }
if (size > size + space_before + space_after) { // Check for rollover.
const size_t alloc_size = size + space_before + space_after;
if (size > alloc_size) { // Check for rollover.
return NULL; return NULL;
} }
NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
u_char* ptr = (u_char*)::malloc(size + space_before + space_after);
u_char* ptr;
if (MallocMaxTestWords > 0) {
ptr = testMalloc(alloc_size);
} else {
ptr = (u_char*)::malloc(alloc_size);
}
#ifdef ASSERT #ifdef ASSERT
if (ptr == NULL) return NULL; if (ptr == NULL) return NULL;
......
...@@ -68,6 +68,7 @@ int MemTracker::_thread_count = 255; ...@@ -68,6 +68,7 @@ int MemTracker::_thread_count = 255;
volatile jint MemTracker::_pooled_recorder_count = 0; volatile jint MemTracker::_pooled_recorder_count = 0;
volatile unsigned long MemTracker::_processing_generation = 0; volatile unsigned long MemTracker::_processing_generation = 0;
volatile bool MemTracker::_worker_thread_idle = false; volatile bool MemTracker::_worker_thread_idle = false;
volatile bool MemTracker::_slowdown_calling_thread = false;
debug_only(intx MemTracker::_main_thread_tid = 0;) debug_only(intx MemTracker::_main_thread_tid = 0;)
NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;)
...@@ -364,6 +365,12 @@ void MemTracker::create_memory_record(address addr, MEMFLAGS flags, ...@@ -364,6 +365,12 @@ void MemTracker::create_memory_record(address addr, MEMFLAGS flags,
} }
if (thread != NULL) { if (thread != NULL) {
// slow down all calling threads except NMT worker thread, so it
// can catch up.
if (_slowdown_calling_thread && thread != _worker_thread) {
os::yield_all();
}
if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) { if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) {
JavaThread* java_thread = (JavaThread*)thread; JavaThread* java_thread = (JavaThread*)thread;
JavaThreadState state = java_thread->thread_state(); JavaThreadState state = java_thread->thread_state();
...@@ -442,6 +449,7 @@ void MemTracker::enqueue_pending_recorder(MemRecorder* rec) { ...@@ -442,6 +449,7 @@ void MemTracker::enqueue_pending_recorder(MemRecorder* rec) {
#define MAX_SAFEPOINTS_TO_SKIP 128 #define MAX_SAFEPOINTS_TO_SKIP 128
#define SAFE_SEQUENCE_THRESHOLD 30 #define SAFE_SEQUENCE_THRESHOLD 30
#define HIGH_GENERATION_THRESHOLD 60 #define HIGH_GENERATION_THRESHOLD 60
#define MAX_RECORDER_THREAD_RATIO 30
void MemTracker::sync() { void MemTracker::sync() {
assert(_tracking_level > NMT_off, "NMT is not enabled"); assert(_tracking_level > NMT_off, "NMT is not enabled");
...@@ -487,6 +495,13 @@ void MemTracker::sync() { ...@@ -487,6 +495,13 @@ void MemTracker::sync() {
pending_recorders = _global_recorder; pending_recorders = _global_recorder;
_global_recorder = NULL; _global_recorder = NULL;
} }
// see if NMT has too many outstanding recorder instances, it usually
// means that worker thread is lagging behind in processing them.
if (!AutoShutdownNMT) {
_slowdown_calling_thread = (MemRecorder::_instance_count > MAX_RECORDER_THREAD_RATIO * _thread_count);
}
// check _worker_thread with lock to avoid racing condition // check _worker_thread with lock to avoid racing condition
if (_worker_thread != NULL) { if (_worker_thread != NULL) {
_worker_thread->at_sync_point(pending_recorders, InstanceKlass::number_of_instance_classes()); _worker_thread->at_sync_point(pending_recorders, InstanceKlass::number_of_instance_classes());
......
...@@ -84,6 +84,7 @@ class MemTracker : AllStatic { ...@@ -84,6 +84,7 @@ class MemTracker : AllStatic {
static inline bool baseline() { return false; } static inline bool baseline() { return false; }
static inline bool has_baseline() { return false; } static inline bool has_baseline() { return false; }
static inline void set_autoShutdown(bool value) { }
static void shutdown(ShutdownReason reason) { } static void shutdown(ShutdownReason reason) { }
static inline bool shutdown_in_progress() { } static inline bool shutdown_in_progress() { }
static bool print_memory_usage(BaselineOutputer& out, size_t unit, static bool print_memory_usage(BaselineOutputer& out, size_t unit,
...@@ -238,6 +239,16 @@ class MemTracker : AllStatic { ...@@ -238,6 +239,16 @@ class MemTracker : AllStatic {
// if native memory tracking tracks callsite // if native memory tracking tracks callsite
static inline bool track_callsite() { return _tracking_level == NMT_detail; } static inline bool track_callsite() { return _tracking_level == NMT_detail; }
// NMT automatically shuts itself down under extreme situation by default.
// When the value is set to false, NMT will try its best to stay alive,
// even it has to slow down VM.
static inline void set_autoShutdown(bool value) {
AutoShutdownNMT = value;
if (AutoShutdownNMT && _slowdown_calling_thread) {
_slowdown_calling_thread = false;
}
}
// shutdown native memory tracking capability. Native memory tracking // shutdown native memory tracking capability. Native memory tracking
// can be shutdown by VM when it encounters low memory scenarios. // can be shutdown by VM when it encounters low memory scenarios.
// Memory tracker should gracefully shutdown itself, and preserve the // Memory tracker should gracefully shutdown itself, and preserve the
...@@ -507,6 +518,10 @@ class MemTracker : AllStatic { ...@@ -507,6 +518,10 @@ class MemTracker : AllStatic {
// although NMT is still procesing current generation, but // although NMT is still procesing current generation, but
// there is not more recorder to process, set idle state // there is not more recorder to process, set idle state
static volatile bool _worker_thread_idle; static volatile bool _worker_thread_idle;
// if NMT should slow down calling thread to allow
// worker thread to catch up
static volatile bool _slowdown_calling_thread;
}; };
#endif // !INCLUDE_NMT #endif // !INCLUDE_NMT
......
...@@ -49,6 +49,9 @@ NMTDCmd::NMTDCmd(outputStream* output, ...@@ -49,6 +49,9 @@ NMTDCmd::NMTDCmd(outputStream* output,
_shutdown("shutdown", "request runtime to shutdown itself and free the " \ _shutdown("shutdown", "request runtime to shutdown itself and free the " \
"memory used by runtime.", "memory used by runtime.",
"BOOLEAN", false, "false"), "BOOLEAN", false, "false"),
_auto_shutdown("autoShutdown", "automatically shutdown itself under " \
"stress situation",
"BOOLEAN", true, "true"),
#ifndef PRODUCT #ifndef PRODUCT
_debug("debug", "print tracker statistics. Debug only, not thread safe", \ _debug("debug", "print tracker statistics. Debug only, not thread safe", \
"BOOLEAN", false, "false"), "BOOLEAN", false, "false"),
...@@ -61,6 +64,7 @@ NMTDCmd::NMTDCmd(outputStream* output, ...@@ -61,6 +64,7 @@ NMTDCmd::NMTDCmd(outputStream* output,
_dcmdparser.add_dcmd_option(&_summary_diff); _dcmdparser.add_dcmd_option(&_summary_diff);
_dcmdparser.add_dcmd_option(&_detail_diff); _dcmdparser.add_dcmd_option(&_detail_diff);
_dcmdparser.add_dcmd_option(&_shutdown); _dcmdparser.add_dcmd_option(&_shutdown);
_dcmdparser.add_dcmd_option(&_auto_shutdown);
#ifndef PRODUCT #ifndef PRODUCT
_dcmdparser.add_dcmd_option(&_debug); _dcmdparser.add_dcmd_option(&_debug);
#endif #endif
...@@ -84,17 +88,19 @@ void NMTDCmd::execute(TRAPS) { ...@@ -84,17 +88,19 @@ void NMTDCmd::execute(TRAPS) {
} }
int nopt = 0; int nopt = 0;
if(_summary.is_set() && _summary.value()) { ++nopt; } if (_summary.is_set() && _summary.value()) { ++nopt; }
if(_detail.is_set() && _detail.value()) { ++nopt; } if (_detail.is_set() && _detail.value()) { ++nopt; }
if(_baseline.is_set() && _baseline.value()) { ++nopt; } if (_baseline.is_set() && _baseline.value()) { ++nopt; }
if(_summary_diff.is_set() && _summary_diff.value()) { ++nopt; } if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; }
if(_detail_diff.is_set() && _detail_diff.value()) { ++nopt; } if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; }
if(_shutdown.is_set() && _shutdown.value()) { ++nopt; } if (_shutdown.is_set() && _shutdown.value()) { ++nopt; }
if (_auto_shutdown.is_set()) { ++nopt; }
#ifndef PRODUCT #ifndef PRODUCT
if(_debug.is_set() && _debug.value()) { ++nopt; } if (_debug.is_set() && _debug.value()) { ++nopt; }
#endif #endif
if(nopt > 1) { if (nopt > 1) {
output()->print_cr("At most one of the following option can be specified: " \ output()->print_cr("At most one of the following option can be specified: " \
"summary, detail, baseline, summary.diff, detail.diff, shutdown" "summary, detail, baseline, summary.diff, detail.diff, shutdown"
#ifndef PRODUCT #ifndef PRODUCT
...@@ -156,6 +162,8 @@ void NMTDCmd::execute(TRAPS) { ...@@ -156,6 +162,8 @@ void NMTDCmd::execute(TRAPS) {
MemTracker::shutdown(MemTracker::NMT_shutdown_user); MemTracker::shutdown(MemTracker::NMT_shutdown_user);
output()->print_cr("Shutdown is in progress, it will take a few moments to " \ output()->print_cr("Shutdown is in progress, it will take a few moments to " \
"completely shutdown"); "completely shutdown");
} else if (_auto_shutdown.is_set()) {
MemTracker::set_autoShutdown(_auto_shutdown.value());
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();
output()->print_cr("Unknown command"); output()->print_cr("Unknown command");
......
...@@ -39,6 +39,7 @@ class NMTDCmd: public DCmdWithParser { ...@@ -39,6 +39,7 @@ class NMTDCmd: public DCmdWithParser {
DCmdArgument<bool> _summary_diff; DCmdArgument<bool> _summary_diff;
DCmdArgument<bool> _detail_diff; DCmdArgument<bool> _detail_diff;
DCmdArgument<bool> _shutdown; DCmdArgument<bool> _shutdown;
DCmdArgument<bool> _auto_shutdown;
#ifndef PRODUCT #ifndef PRODUCT
DCmdArgument<bool> _debug; DCmdArgument<bool> _debug;
#endif #endif
......
#!/bin/sh #!/bin/sh
#
# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
## ##
## @test ## @test
## @bug 6878713 ## @bug 6878713
## @bug 7030610
## @bug 7037122
## @bug 7123945
## @summary Verifier heap corruption, relating to backward jsrs ## @summary Verifier heap corruption, relating to backward jsrs
## @run shell/timeout=120 Test6878713.sh ## @run shell Test6878713.sh
## ##
if [ "${TESTSRC}" = "" ] if [ "${TESTSRC}" = "" ]
...@@ -49,23 +77,98 @@ case "$OS" in ...@@ -49,23 +77,98 @@ case "$OS" in
;; ;;
esac esac
JEMMYPATH=${CPAPPEND} CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH
CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH
THIS_DIR=`pwd`
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version
${TESTJAVA}${FS}bin${FS}jar xvf ${TESTSRC}${FS}testcase.jar TARGET_CLASS=OOMCrashClass1960_2
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} OOMCrashClass1960_2 > test.out 2>&1 echo "INFO: extracting the target class."
${TESTJAVA}${FS}bin${FS}jar xvf \
${TESTSRC}${FS}testcase.jar ${TARGET_CLASS}.class
if [ -s core -o -s "hs_*.log" ] # remove any hs_err_pid that might exist here
then rm -f hs_err_pid*.log
cat hs*.log
echo "Test Failed" echo "INFO: checking for 32-bit versus 64-bit VM."
exit 1 ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version 2>&1 \
| grep "64-Bit [^ ][^ ]* VM" > /dev/null 2>&1
status="$?"
if [ "$status" = 0 ]; then
echo "INFO: testing a 64-bit VM."
is_64_bit=true
else
echo "INFO: testing a 32-bit VM."
fi
if [ "$is_64_bit" = true ]; then
# limit is 768MB in 8-byte words (1024 * 1024 * 768 / 8) == 100663296
MALLOC_MAX=100663296
else else
echo "Test Passed" # limit is 768MB in 4-byte words (1024 * 1024 * 768 / 4) == 201326592
exit 0 MALLOC_MAX=201326592
fi
echo "INFO: MALLOC_MAX=$MALLOC_MAX"
echo "INFO: executing the target class."
# -XX:+PrintCommandLineFlags for debugging purposes
# -XX:+IgnoreUnrecognizedVMOptions so test will run on a VM without
# the new -XX:MallocMaxTestWords option
# -XX:+UnlockDiagnosticVMOptions so we can use -XX:MallocMaxTestWords
# -XX:MallocMaxTestWords limits malloc to $MALLOC_MAX
${TESTJAVA}${FS}bin${FS}java \
-XX:+PrintCommandLineFlags \
-XX:+IgnoreUnrecognizedVMOptions \
-XX:+UnlockDiagnosticVMOptions \
-XX:MallocMaxTestWords=$MALLOC_MAX \
${TESTVMOPTS} ${TARGET_CLASS} > test.out 2>&1
echo "INFO: begin contents of test.out:"
cat test.out
echo "INFO: end contents of test.out."
echo "INFO: checking for memory allocation error message."
# We are looking for this specific memory allocation failure mesg so
# we know we exercised the right allocation path with the test class:
MESG1="Native memory allocation (malloc) failed to allocate 25696531[0-9][0-9] bytes"
grep "$MESG1" test.out
status="$?"
if [ "$status" = 0 ]; then
echo "INFO: found expected memory allocation error message."
else
echo "INFO: did not find expected memory allocation error message."
# If we didn't find MESG1 above, then there are several scenarios:
# 1) -XX:MallocMaxTestWords is not supported by the current VM and we
# didn't fail TARGET_CLASS's memory allocation attempt; instead
# we failed to find TARGET_CLASS's main() method. The TARGET_CLASS
# is designed to provoke a memory allocation failure during class
# loading; we actually don't care about running the class which is
# why it doesn't have a main() method.
# 2) we failed a memory allocation, but not the one we were looking
# so it might be that TARGET_CLASS no longer tickles the same
# memory allocation code path
# 3) TARGET_CLASS reproduces the failure mode (SIGSEGV) fixed by
# 6878713 because the test is running on a pre-fix VM.
echo "INFO: checking for no main() method message."
MESG2="Error: Main method not found in class"
grep "$MESG2" test.out
status="$?"
if [ "$status" = 0 ]; then
echo "INFO: found no main() method message."
else
echo "FAIL: did not find no main() method message."
# status is non-zero for exit below
if [ -s hs_err_pid*.log ]; then
echo "INFO: begin contents of hs_err_pid file:"
cat hs_err_pid*.log
echo "INFO: end contents of hs_err_pid file."
fi
fi
fi
if [ "$status" = 0 ]; then
echo "PASS: test found one of the expected messages."
fi fi
exit "$status"
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
/*
* @test
* @key regression
* @bug 8010389
* @run main/othervm -Djava.library.path=. VMThreadDlopen
*/
public class VMThreadDlopen {
public static void main(String[] args) throws Exception {
File file = new File("libbroken.so");
file.createNewFile();
try {
System.loadLibrary("broken");
} catch (UnsatisfiedLinkError e) {
e.printStackTrace();
// expected
}
}
}
...@@ -33,17 +33,17 @@ import com.oracle.java.testlibrary.*; ...@@ -33,17 +33,17 @@ import com.oracle.java.testlibrary.*;
public class BooleanFlagWithInvalidValue { public class BooleanFlagWithInvalidValue {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UseLargePages=8", "-version"); "-XX:+PrintWarnings=8", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start()); OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Improperly specified VM option 'UseLargePages=8'"); output.shouldContain("Improperly specified VM option 'PrintWarnings=8'");
output.shouldHaveExitValue(1); output.shouldHaveExitValue(1);
pb = ProcessTools.createJavaProcessBuilder( pb = ProcessTools.createJavaProcessBuilder(
"-XX:-UseLargePages=8", "-version"); "-XX:-PrintWarnings=8", "-version");
output = new OutputAnalyzer(pb.start()); output = new OutputAnalyzer(pb.start());
output.shouldContain("Improperly specified VM option 'UseLargePages=8'"); output.shouldContain("Improperly specified VM option 'PrintWarnings=8'");
output.shouldHaveExitValue(1); output.shouldHaveExitValue(1);
} }
} }
...@@ -33,10 +33,10 @@ import com.oracle.java.testlibrary.*; ...@@ -33,10 +33,10 @@ import com.oracle.java.testlibrary.*;
public class FlagWithInvalidValue { public class FlagWithInvalidValue {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:ObjectAlignmentInBytes=v", "-version"); "-XX:MaxRAMFraction=v", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start()); OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Improperly specified VM option 'ObjectAlignmentInBytes=v'"); output.shouldContain("Improperly specified VM option 'MaxRAMFraction=v'");
output.shouldHaveExitValue(1); output.shouldHaveExitValue(1);
} }
} }
...@@ -33,17 +33,17 @@ import com.oracle.java.testlibrary.*; ...@@ -33,17 +33,17 @@ import com.oracle.java.testlibrary.*;
public class NonBooleanFlagWithInvalidBooleanPrefix { public class NonBooleanFlagWithInvalidBooleanPrefix {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:-ObjectAlignmentInBytes=16", "-version"); "-XX:-MaxRAMFraction=16", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start()); OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'"); output.shouldContain("Unexpected +/- setting in VM option 'MaxRAMFraction=16'");
output.shouldHaveExitValue(1); output.shouldHaveExitValue(1);
pb = ProcessTools.createJavaProcessBuilder( pb = ProcessTools.createJavaProcessBuilder(
"-XX:+ObjectAlignmentInBytes=16", "-version"); "-XX:+MaxRAMFraction=16", "-version");
output = new OutputAnalyzer(pb.start()); output = new OutputAnalyzer(pb.start());
output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'"); output.shouldContain("Unexpected +/- setting in VM option 'MaxRAMFraction=16'");
output.shouldHaveExitValue(1); output.shouldHaveExitValue(1);
} }
......
...@@ -43,7 +43,7 @@ public class BaselineWithParameter { ...@@ -43,7 +43,7 @@ public class BaselineWithParameter {
// Run 'jcmd <pid> VM.native_memory baseline=false' // Run 'jcmd <pid> VM.native_memory baseline=false'
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"}); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"});
pb.start(); pb.start().waitFor();
// Run 'jcmd <pid> VM.native_memory summary=false' // Run 'jcmd <pid> VM.native_memory summary=false'
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary=false"}); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary=false"});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册