Thu, 12 May 2011 17:36:45 -0700
Merge
1.1 --- a/make/solaris/makefiles/saproc.make Thu May 12 15:05:22 2011 -0700 1.2 +++ b/make/solaris/makefiles/saproc.make Thu May 12 17:36:45 2011 -0700 1.3 @@ -57,24 +57,27 @@ 1.4 endif 1.5 1.6 # The libproc Pstack_iter() interface changed in Nevada-B159. 1.7 -# This logic needs to match 1.8 +# Use 'uname -r -v' to determine the Solaris version as per 1.9 +# Solaris Nevada team request. This logic needs to match: 1.10 # agent/src/os/solaris/proc/saproc.cpp: set_has_newer_Pstack_iter(): 1.11 # - skip SunOS 4 or older 1.12 # - skip Solaris 10 or older 1.13 -# - skip two digit Nevada builds 1.14 -# - skip three digit Nevada builds thru 149 1.15 -# - skip Nevada builds 150-158 1.16 +# - skip two digit internal Nevada builds 1.17 +# - skip three digit internal Nevada builds thru 149 1.18 +# - skip internal Nevada builds 150-158 1.19 +# - if not skipped, print define for Nevada-B159 or later 1.20 SOLARIS_11_B159_OR_LATER := \ 1.21 $(shell uname -r -v \ 1.22 - | sed -n ' \ 1.23 - /^[0-3]\. /b \ 1.24 - /^5\.[0-9] /b \ 1.25 - /^5\.10 /b \ 1.26 - / snv_[0-9][0-9]$/b \ 1.27 - / snv_[01][0-4][0-9]$/b \ 1.28 - / snv_15[0-8]$/b \ 1.29 - s/.*/-DSOLARIS_11_B159_OR_LATER/p \ 1.30 - ') 1.31 + | sed -n \ 1.32 + -e '/^[0-4]\. /b' \ 1.33 + -e '/^5\.[0-9] /b' \ 1.34 + -e '/^5\.10 /b' \ 1.35 + -e '/ snv_[0-9][0-9]$/b' \ 1.36 + -e '/ snv_[01][0-4][0-9]$/b' \ 1.37 + -e '/ snv_15[0-8]$/b' \ 1.38 + -e 's/.*/-DSOLARIS_11_B159_OR_LATER/' \ 1.39 + -e 'p' \ 1.40 + ) 1.41 1.42 # Uncomment the following to simulate building on Nevada-B159 or later 1.43 # when actually building on Nevada-B158 or earlier:
2.1 --- a/src/share/vm/classfile/vmSymbols.hpp Thu May 12 15:05:22 2011 -0700 2.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu May 12 17:36:45 2011 -0700 2.3 @@ -471,6 +471,13 @@ 2.4 template(sun_management_ManagementFactory, "sun/management/ManagementFactory") \ 2.5 template(sun_management_Sensor, "sun/management/Sensor") \ 2.6 template(sun_management_Agent, "sun/management/Agent") \ 2.7 + template(sun_management_GarbageCollectorImpl, "sun/management/GarbageCollectorImpl") \ 2.8 + template(getGcInfoBuilder_name, "getGcInfoBuilder") \ 2.9 + template(getGcInfoBuilder_signature, "()Lsun/management/GcInfoBuilder;") \ 2.10 + template(com_sun_management_GcInfo, "com/sun/management/GcInfo") \ 2.11 + template(com_sun_management_GcInfo_constructor_signature, "(Lsun/management/GcInfoBuilder;JJJ[Ljava/lang/management/MemoryUsage;[Ljava/lang/management/MemoryUsage;[Ljava/lang/Object;)V") \ 2.12 + template(createGCNotification_name, "createGCNotification") \ 2.13 + template(createGCNotification_signature, "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/sun/management/GcInfo;)V") \ 2.14 template(createMemoryPoolMBean_name, "createMemoryPoolMBean") \ 2.15 template(createMemoryManagerMBean_name, "createMemoryManagerMBean") \ 2.16 template(createGarbageCollectorMBean_name, "createGarbageCollectorMBean") \ 2.17 @@ -488,6 +495,7 @@ 2.18 template(java_lang_management_MemoryPoolMXBean, "java/lang/management/MemoryPoolMXBean") \ 2.19 template(java_lang_management_MemoryManagerMXBean, "java/lang/management/MemoryManagerMXBean") \ 2.20 template(java_lang_management_GarbageCollectorMXBean,"java/lang/management/GarbageCollectorMXBean") \ 2.21 + template(gcInfoBuilder_name, "gcInfoBuilder") \ 2.22 template(createMemoryPool_name, "createMemoryPool") \ 2.23 template(createMemoryManager_name, "createMemoryManager") \ 2.24 template(createGarbageCollector_name, "createGarbageCollector") \
3.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu May 12 15:05:22 2011 -0700 3.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu May 12 17:36:45 2011 -0700 3.3 @@ -2026,7 +2026,7 @@ 3.4 } 3.5 3.6 { 3.7 - TraceCMSMemoryManagerStats(); 3.8 + TraceCMSMemoryManagerStats tmms(gch->gc_cause()); 3.9 } 3.10 GenMarkSweep::invoke_at_safepoint(_cmsGen->level(), 3.11 ref_processor(), clear_all_soft_refs); 3.12 @@ -3479,7 +3479,7 @@ 3.13 void CMSCollector::checkpointRootsInitial(bool asynch) { 3.14 assert(_collectorState == InitialMarking, "Wrong collector state"); 3.15 check_correct_thread_executing(); 3.16 - TraceCMSMemoryManagerStats tms(_collectorState); 3.17 + TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause()); 3.18 3.19 ReferenceProcessor* rp = ref_processor(); 3.20 SpecializationStats::clear(); 3.21 @@ -4858,7 +4858,8 @@ 3.22 // world is stopped at this checkpoint 3.23 assert(SafepointSynchronize::is_at_safepoint(), 3.24 "world should be stopped"); 3.25 - TraceCMSMemoryManagerStats tms(_collectorState); 3.26 + TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause()); 3.27 + 3.28 verify_work_stacks_empty(); 3.29 verify_overflow_empty(); 3.30 3.31 @@ -5993,7 +5994,7 @@ 3.32 verify_work_stacks_empty(); 3.33 verify_overflow_empty(); 3.34 increment_sweep_count(); 3.35 - TraceCMSMemoryManagerStats tms(_collectorState); 3.36 + TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause()); 3.37 3.38 _inter_sweep_timer.stop(); 3.39 _inter_sweep_estimate.sample(_inter_sweep_timer.seconds()); 3.40 @@ -9235,11 +9236,12 @@ 3.41 return res; 3.42 } 3.43 3.44 -TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase): TraceMemoryManagerStats() { 3.45 +TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase, GCCause::Cause cause): TraceMemoryManagerStats() { 3.46 3.47 switch (phase) { 3.48 case CMSCollector::InitialMarking: 3.49 initialize(true /* fullGC */ , 3.50 + cause /* cause of the GC */, 3.51 true /* recordGCBeginTime */, 3.52 true /* recordPreGCUsage */, 3.53 false /* recordPeakUsage */, 3.54 @@ -9251,6 +9253,7 @@ 3.55 3.56 case CMSCollector::FinalMarking: 3.57 initialize(true /* fullGC */ , 3.58 + cause /* cause of the GC */, 3.59 false /* recordGCBeginTime */, 3.60 false /* recordPreGCUsage */, 3.61 false /* recordPeakUsage */, 3.62 @@ -9262,6 +9265,7 @@ 3.63 3.64 case CMSCollector::Sweeping: 3.65 initialize(true /* fullGC */ , 3.66 + cause /* cause of the GC */, 3.67 false /* recordGCBeginTime */, 3.68 false /* recordPreGCUsage */, 3.69 true /* recordPeakUsage */, 3.70 @@ -9277,8 +9281,9 @@ 3.71 } 3.72 3.73 // when bailing out of cms in concurrent mode failure 3.74 -TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(): TraceMemoryManagerStats() { 3.75 +TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(GCCause::Cause cause): TraceMemoryManagerStats() { 3.76 initialize(true /* fullGC */ , 3.77 + cause /* cause of the GC */, 3.78 true /* recordGCBeginTime */, 3.79 true /* recordPreGCUsage */, 3.80 true /* recordPeakUsage */,
4.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu May 12 15:05:22 2011 -0700 4.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu May 12 17:36:45 2011 -0700 4.3 @@ -1895,8 +1895,8 @@ 4.4 class TraceCMSMemoryManagerStats : public TraceMemoryManagerStats { 4.5 4.6 public: 4.7 - TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase); 4.8 - TraceCMSMemoryManagerStats(); 4.9 + TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase, GCCause::Cause cause); 4.10 + TraceCMSMemoryManagerStats(GCCause::Cause cause); 4.11 }; 4.12 4.13
5.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu May 12 15:05:22 2011 -0700 5.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu May 12 17:36:45 2011 -0700 5.3 @@ -1162,7 +1162,7 @@ 5.4 PrintGC, true, gclog_or_tty); 5.5 5.6 TraceCollectorStats tcs(g1mm()->full_collection_counters()); 5.7 - TraceMemoryManagerStats tms(true /* fullGC */); 5.8 + TraceMemoryManagerStats tms(true /* fullGC */, gc_cause()); 5.9 5.10 double start = os::elapsedTime(); 5.11 g1_policy()->record_full_collection_start(); 5.12 @@ -3202,7 +3202,7 @@ 5.13 TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty); 5.14 5.15 TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); 5.16 - TraceMemoryManagerStats tms(false /* fullGC */); 5.17 + TraceMemoryManagerStats tms(false /* fullGC */, gc_cause()); 5.18 5.19 // If the secondary_free_list is not empty, append it to the 5.20 // free_list. No need to wait for the cleanup operation to finish;
6.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu May 12 15:05:22 2011 -0700 6.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu May 12 17:36:45 2011 -0700 6.3 @@ -173,7 +173,7 @@ 6.4 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); 6.5 TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty); 6.6 TraceCollectorStats tcs(counters()); 6.7 - TraceMemoryManagerStats tms(true /* Full GC */); 6.8 + TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); 6.9 6.10 if (TraceGen1Time) accumulated_time()->start(); 6.11
7.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu May 12 15:05:22 2011 -0700 7.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu May 12 17:36:45 2011 -0700 7.3 @@ -2057,7 +2057,7 @@ 7.4 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); 7.5 TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty); 7.6 TraceCollectorStats tcs(counters()); 7.7 - TraceMemoryManagerStats tms(true /* Full GC */); 7.8 + TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); 7.9 7.10 if (TraceGen1Time) accumulated_time()->start(); 7.11
8.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu May 12 15:05:22 2011 -0700 8.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu May 12 17:36:45 2011 -0700 8.3 @@ -322,7 +322,7 @@ 8.4 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); 8.5 TraceTime t1("GC", PrintGC, !PrintGCDetails, gclog_or_tty); 8.6 TraceCollectorStats tcs(counters()); 8.7 - TraceMemoryManagerStats tms(false /* not full GC */); 8.8 + TraceMemoryManagerStats tms(false /* not full GC */,gc_cause); 8.9 8.10 if (TraceGen0Time) accumulated_time()->start(); 8.11
9.1 --- a/src/share/vm/memory/genCollectedHeap.cpp Thu May 12 15:05:22 2011 -0700 9.2 +++ b/src/share/vm/memory/genCollectedHeap.cpp Thu May 12 17:36:45 2011 -0700 9.3 @@ -537,7 +537,7 @@ 9.4 // Timer for individual generations. Last argument is false: no CR 9.5 TraceTime t1(_gens[i]->short_name(), PrintGCDetails, false, gclog_or_tty); 9.6 TraceCollectorStats tcs(_gens[i]->counters()); 9.7 - TraceMemoryManagerStats tmms(_gens[i]->kind()); 9.8 + TraceMemoryManagerStats tmms(_gens[i]->kind(),gc_cause()); 9.9 9.10 size_t prev_used = _gens[i]->used(); 9.11 _gens[i]->stat_record()->invocations++;
10.1 --- a/src/share/vm/runtime/serviceThread.cpp Thu May 12 15:05:22 2011 -0700 10.2 +++ b/src/share/vm/runtime/serviceThread.cpp Thu May 12 17:36:45 2011 -0700 10.3 @@ -28,6 +28,7 @@ 10.4 #include "runtime/serviceThread.hpp" 10.5 #include "runtime/mutexLocker.hpp" 10.6 #include "prims/jvmtiImpl.hpp" 10.7 +#include "services/gcNotifier.hpp" 10.8 10.9 ServiceThread* ServiceThread::_instance = NULL; 10.10 10.11 @@ -81,6 +82,7 @@ 10.12 while (true) { 10.13 bool sensors_changed = false; 10.14 bool has_jvmti_events = false; 10.15 + bool has_gc_notification_event = false; 10.16 JvmtiDeferredEvent jvmti_event; 10.17 { 10.18 // Need state transition ThreadBlockInVM so that this thread 10.19 @@ -95,9 +97,10 @@ 10.20 10.21 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); 10.22 while (!(sensors_changed = LowMemoryDetector::has_pending_requests()) && 10.23 - !(has_jvmti_events = JvmtiDeferredEventQueue::has_events())) { 10.24 + !(has_jvmti_events = JvmtiDeferredEventQueue::has_events()) && 10.25 + !(has_gc_notification_event = GCNotifier::has_event())) { 10.26 // wait until one of the sensors has pending requests, or there is a 10.27 - // pending JVMTI event to post 10.28 + // pending JVMTI event or JMX GC notification to post 10.29 Service_lock->wait(Mutex::_no_safepoint_check_flag); 10.30 } 10.31 10.32 @@ -113,6 +116,10 @@ 10.33 if (sensors_changed) { 10.34 LowMemoryDetector::process_sensor_changes(jt); 10.35 } 10.36 + 10.37 + if(has_gc_notification_event) { 10.38 + GCNotifier::sendNotification(CHECK); 10.39 + } 10.40 } 10.41 } 10.42
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/share/vm/services/gcNotifier.cpp Thu May 12 17:36:45 2011 -0700 11.3 @@ -0,0 +1,216 @@ 11.4 +/* 11.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.7 + * 11.8 + * This code is free software; you can redistribute it and/or modify it 11.9 + * under the terms of the GNU General Public License version 2 only, as 11.10 + * published by the Free Software Foundation. 11.11 + * 11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11.15 + * version 2 for more details (a copy is included in the LICENSE file that 11.16 + * accompanied this code). 11.17 + * 11.18 + * You should have received a copy of the GNU General Public License version 11.19 + * 2 along with this work; if not, write to the Free Software Foundation, 11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 11.21 + * 11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 11.23 + * or visit www.oracle.com if you need additional information or have any 11.24 + * questions. 11.25 + * 11.26 + */ 11.27 + 11.28 +#include "precompiled.hpp" 11.29 +#include "classfile/systemDictionary.hpp" 11.30 +#include "classfile/vmSymbols.hpp" 11.31 +#include "oops/oop.inline.hpp" 11.32 +#include "runtime/interfaceSupport.hpp" 11.33 +#include "runtime/java.hpp" 11.34 +#include "runtime/javaCalls.hpp" 11.35 +#include "runtime/mutex.hpp" 11.36 +#include "runtime/mutexLocker.hpp" 11.37 +#include "services/gcNotifier.hpp" 11.38 +#include "services/management.hpp" 11.39 +#include "services/memoryService.hpp" 11.40 +#include "memoryManager.hpp" 11.41 +#include "memory/oopFactory.hpp" 11.42 + 11.43 +GCNotificationRequest *GCNotifier::first_request = NULL; 11.44 +GCNotificationRequest *GCNotifier::last_request = NULL; 11.45 + 11.46 +void GCNotifier::pushNotification(GCMemoryManager *mgr, const char *action, const char *cause) { 11.47 + // Make a copy of the last GC statistics 11.48 + // GC may occur between now and the creation of the notification 11.49 + int num_pools = MemoryService::num_memory_pools(); 11.50 + GCStatInfo* stat = new GCStatInfo(num_pools); 11.51 + mgr->get_last_gc_stat(stat); 11.52 + GCNotificationRequest *request = new GCNotificationRequest(os::javaTimeMillis(),mgr,action,cause,stat); 11.53 + addRequest(request); 11.54 + } 11.55 + 11.56 +void GCNotifier::addRequest(GCNotificationRequest *request) { 11.57 + MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); 11.58 + if(first_request == NULL) { 11.59 + first_request = request; 11.60 + } else { 11.61 + last_request->next = request; 11.62 + } 11.63 + last_request = request; 11.64 + Service_lock->notify_all(); 11.65 +} 11.66 + 11.67 +GCNotificationRequest *GCNotifier::getRequest() { 11.68 + MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); 11.69 + GCNotificationRequest *request = first_request; 11.70 + if(first_request != NULL) { 11.71 + first_request = first_request->next; 11.72 + } 11.73 + return request; 11.74 +} 11.75 + 11.76 +bool GCNotifier::has_event() { 11.77 + return first_request != NULL; 11.78 +} 11.79 + 11.80 +static Handle getGcInfoBuilder(GCMemoryManager *gcManager,TRAPS) { 11.81 + 11.82 + klassOop k = Management::sun_management_GarbageCollectorImpl_klass(CHECK_NH); 11.83 + instanceKlassHandle gcMBeanKlass (THREAD, k); 11.84 + 11.85 + instanceOop i = gcManager->get_memory_manager_instance(THREAD); 11.86 + instanceHandle ih(THREAD, i); 11.87 + 11.88 + JavaValue result(T_OBJECT); 11.89 + JavaCallArguments args(ih); 11.90 + 11.91 + JavaCalls::call_virtual(&result, 11.92 + gcMBeanKlass, 11.93 + vmSymbols::getGcInfoBuilder_name(), 11.94 + vmSymbols::getGcInfoBuilder_signature(), 11.95 + &args, 11.96 + CHECK_NH); 11.97 + return Handle(THREAD,(oop)result.get_jobject()); 11.98 + 11.99 +} 11.100 + 11.101 +static Handle createGcInfo(GCMemoryManager *gcManager, GCStatInfo *gcStatInfo,TRAPS) { 11.102 + 11.103 + // Fill the arrays of MemoryUsage objects with before and after GC 11.104 + // per pool memory usage 11.105 + 11.106 + klassOop muKlass = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); objArrayOop bu = oopFactory::new_objArray( muKlass,MemoryService::num_memory_pools(), CHECK_NH); 11.107 + objArrayHandle usage_before_gc_ah(THREAD, bu); 11.108 + objArrayOop au = oopFactory::new_objArray(muKlass,MemoryService::num_memory_pools(), CHECK_NH); 11.109 + objArrayHandle usage_after_gc_ah(THREAD, au); 11.110 + 11.111 + for (int i = 0; i < MemoryService::num_memory_pools(); i++) { 11.112 + Handle before_usage = MemoryService::create_MemoryUsage_obj(gcStatInfo->before_gc_usage_for_pool(i), CHECK_NH); 11.113 + Handle after_usage; 11.114 + 11.115 + MemoryUsage u = gcStatInfo->after_gc_usage_for_pool(i); 11.116 + if (u.max_size() == 0 && u.used() > 0) { 11.117 + // If max size == 0, this pool is a survivor space. 11.118 + // Set max size = -1 since the pools will be swapped after GC. 11.119 + MemoryUsage usage(u.init_size(), u.used(), u.committed(), (size_t)-1); 11.120 + after_usage = MemoryService::create_MemoryUsage_obj(usage, CHECK_NH); 11.121 + } else { 11.122 + after_usage = MemoryService::create_MemoryUsage_obj(u, CHECK_NH); 11.123 + } 11.124 + usage_before_gc_ah->obj_at_put(i, before_usage()); 11.125 + usage_after_gc_ah->obj_at_put(i, after_usage()); 11.126 + } 11.127 + 11.128 + // Current implementation only has 1 attribute (number of GC threads) 11.129 + // The type is 'I' 11.130 + objArrayOop extra_args_array = oopFactory::new_objArray(SystemDictionary::Integer_klass(), 1, CHECK_NH); 11.131 + objArrayHandle extra_array (THREAD, extra_args_array); 11.132 + klassOop itKlass= SystemDictionary::Integer_klass(); 11.133 + instanceKlassHandle intK(THREAD, itKlass); 11.134 + 11.135 + instanceHandle extra_arg_val = intK->allocate_instance_handle(CHECK_NH); 11.136 + 11.137 + { 11.138 + JavaValue res(T_VOID); 11.139 + JavaCallArguments argsInt; 11.140 + argsInt.push_oop(extra_arg_val); 11.141 + argsInt.push_int(gcManager->num_gc_threads()); 11.142 + 11.143 + JavaCalls::call_special(&res, 11.144 + intK, 11.145 + vmSymbols::object_initializer_name(), 11.146 + vmSymbols::int_void_signature(), 11.147 + &argsInt, 11.148 + CHECK_NH); 11.149 + } 11.150 + extra_array->obj_at_put(0,extra_arg_val()); 11.151 + 11.152 + klassOop gcInfoklass = Management::com_sun_management_GcInfo_klass(CHECK_NH); 11.153 + instanceKlassHandle ik (THREAD,gcInfoklass); 11.154 + 11.155 + Handle gcInfo_instance = ik->allocate_instance_handle(CHECK_NH); 11.156 + 11.157 + JavaValue constructor_result(T_VOID); 11.158 + JavaCallArguments constructor_args(16); 11.159 + constructor_args.push_oop(gcInfo_instance); 11.160 + constructor_args.push_oop(getGcInfoBuilder(gcManager,THREAD)); 11.161 + constructor_args.push_long(gcStatInfo->gc_index()); 11.162 + constructor_args.push_long(gcStatInfo->start_time()); 11.163 + constructor_args.push_long(gcStatInfo->end_time()); 11.164 + constructor_args.push_oop(usage_before_gc_ah); 11.165 + constructor_args.push_oop(usage_after_gc_ah); 11.166 + constructor_args.push_oop(extra_array); 11.167 + 11.168 + JavaCalls::call_special(&constructor_result, 11.169 + ik, 11.170 + vmSymbols::object_initializer_name(), 11.171 + vmSymbols::com_sun_management_GcInfo_constructor_signature(), 11.172 + &constructor_args, 11.173 + CHECK_NH); 11.174 + 11.175 + return Handle(gcInfo_instance()); 11.176 +} 11.177 + 11.178 +void GCNotifier::sendNotification(TRAPS) { 11.179 + ResourceMark rm(THREAD); 11.180 + GCNotificationRequest *request = getRequest(); 11.181 + if(request != NULL) { 11.182 + Handle objGcInfo = createGcInfo(request->gcManager,request->gcStatInfo,THREAD); 11.183 + 11.184 + Handle objName = java_lang_String::create_from_platform_dependent_str(request->gcManager->name(), CHECK); 11.185 + Handle objAction = java_lang_String::create_from_platform_dependent_str(request->gcAction, CHECK); 11.186 + Handle objCause = java_lang_String::create_from_platform_dependent_str(request->gcCause, CHECK); 11.187 + 11.188 + klassOop k = Management::sun_management_GarbageCollectorImpl_klass(CHECK); 11.189 + instanceKlassHandle gc_mbean_klass (THREAD, k); 11.190 + 11.191 + instanceOop gc_mbean = request->gcManager->get_memory_manager_instance(THREAD); 11.192 + instanceHandle gc_mbean_h(THREAD, gc_mbean); 11.193 + if (!gc_mbean_h->is_a(k)) { 11.194 + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 11.195 + "This GCMemoryManager doesn't have a GarbageCollectorMXBean"); 11.196 + } 11.197 + 11.198 + JavaValue result(T_VOID); 11.199 + JavaCallArguments args(gc_mbean_h); 11.200 + args.push_long(request->timestamp); 11.201 + args.push_oop(objName); 11.202 + args.push_oop(objAction); 11.203 + args.push_oop(objCause); 11.204 + args.push_oop(objGcInfo); 11.205 + 11.206 + JavaCalls::call_virtual(&result, 11.207 + gc_mbean_klass, 11.208 + vmSymbols::createGCNotification_name(), 11.209 + vmSymbols::createGCNotification_signature(), 11.210 + &args, 11.211 + CHECK); 11.212 + if (HAS_PENDING_EXCEPTION) { 11.213 + CLEAR_PENDING_EXCEPTION; 11.214 + } 11.215 + 11.216 + delete request; 11.217 + } 11.218 +} 11.219 +
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/share/vm/services/gcNotifier.hpp Thu May 12 17:36:45 2011 -0700 12.3 @@ -0,0 +1,69 @@ 12.4 +/* 12.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12.7 + * 12.8 + * This code is free software; you can redistribute it and/or modify it 12.9 + * under the terms of the GNU General Public License version 2 only, as 12.10 + * published by the Free Software Foundation. 12.11 + * 12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12.15 + * version 2 for more details (a copy is included in the LICENSE file that 12.16 + * accompanied this code). 12.17 + * 12.18 + * You should have received a copy of the GNU General Public License version 12.19 + * 2 along with this work; if not, write to the Free Software Foundation, 12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 12.21 + * 12.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 12.23 + * or visit www.oracle.com if you need additional information or have any 12.24 + * questions. 12.25 + * 12.26 + */ 12.27 + 12.28 +#ifndef SHARE_VM_SERVICES_GCNOTIFIER_HPP 12.29 +#define SHARE_VM_SERVICES_GCNOTIFIER_HPP 12.30 + 12.31 +#include "memory/allocation.hpp" 12.32 +#include "services/memoryPool.hpp" 12.33 +#include "services/memoryService.hpp" 12.34 +#include "services/memoryManager.hpp" 12.35 + 12.36 +class GCNotificationRequest : public CHeapObj { 12.37 + friend class GCNotifier; 12.38 + GCNotificationRequest *next; 12.39 + jlong timestamp; 12.40 + GCMemoryManager *gcManager; 12.41 + const char *gcAction; 12.42 + const char *gcCause; 12.43 + GCStatInfo *gcStatInfo; 12.44 +public: 12.45 + GCNotificationRequest(jlong ts, GCMemoryManager *manager, const char*action, const char *cause,GCStatInfo *info) { 12.46 + next = NULL; 12.47 + timestamp = ts; 12.48 + gcManager = manager; 12.49 + gcAction = action; 12.50 + gcCause = cause; 12.51 + gcStatInfo = info; 12.52 + } 12.53 + 12.54 + ~GCNotificationRequest() { 12.55 + delete gcStatInfo; 12.56 + } 12.57 +}; 12.58 + 12.59 +class GCNotifier : public AllStatic { 12.60 + friend class ServiceThread; 12.61 +private: 12.62 + static GCNotificationRequest *first_request; 12.63 + static GCNotificationRequest *last_request; 12.64 + static void addRequest(GCNotificationRequest *request); 12.65 + static GCNotificationRequest *getRequest(); 12.66 +public: 12.67 + static void pushNotification(GCMemoryManager *manager, const char *action, const char *cause); 12.68 + static bool has_event(); 12.69 + static void sendNotification(TRAPS); 12.70 +}; 12.71 + 12.72 +#endif // SHARE_VM_SERVICES_GCNOTIFIER_HPP
13.1 --- a/src/share/vm/services/jmm.h Thu May 12 15:05:22 2011 -0700 13.2 +++ b/src/share/vm/services/jmm.h Thu May 12 17:36:45 2011 -0700 13.3 @@ -48,7 +48,7 @@ 13.4 JMM_VERSION_1_0 = 0x20010000, 13.5 JMM_VERSION_1_1 = 0x20010100, // JDK 6 13.6 JMM_VERSION_1_2 = 0x20010200, // JDK 7 13.7 - JMM_VERSION = 0x20010200 13.8 + JMM_VERSION = 0x20010201 13.9 }; 13.10 13.11 typedef struct { 13.12 @@ -293,6 +293,9 @@ 13.13 jlongArray ids, 13.14 jboolean lockedMonitors, 13.15 jboolean lockedSynchronizers); 13.16 + void (JNICALL *SetGCNotificationEnabled) (JNIEnv *env, 13.17 + jobject mgr, 13.18 + jboolean enabled); 13.19 } JmmInterface; 13.20 13.21 #ifdef __cplusplus
14.1 --- a/src/share/vm/services/management.cpp Thu May 12 15:05:22 2011 -0700 14.2 +++ b/src/share/vm/services/management.cpp Thu May 12 17:36:45 2011 -0700 14.3 @@ -42,6 +42,7 @@ 14.4 #include "services/classLoadingService.hpp" 14.5 #include "services/heapDumper.hpp" 14.6 #include "services/lowMemoryDetector.hpp" 14.7 +#include "services/gcNotifier.hpp" 14.8 #include "services/management.hpp" 14.9 #include "services/memoryManager.hpp" 14.10 #include "services/memoryPool.hpp" 14.11 @@ -60,6 +61,8 @@ 14.12 klassOop Management::_memoryManagerMXBean_klass = NULL; 14.13 klassOop Management::_garbageCollectorMXBean_klass = NULL; 14.14 klassOop Management::_managementFactory_klass = NULL; 14.15 +klassOop Management::_garbageCollectorImpl_klass = NULL; 14.16 +klassOop Management::_gcInfo_klass = NULL; 14.17 14.18 jmmOptionalSupport Management::_optional_support = {0}; 14.19 TimeStamp Management::_stamp; 14.20 @@ -179,6 +182,8 @@ 14.21 f->do_oop((oop*) &_memoryManagerMXBean_klass); 14.22 f->do_oop((oop*) &_garbageCollectorMXBean_klass); 14.23 f->do_oop((oop*) &_managementFactory_klass); 14.24 + f->do_oop((oop*) &_garbageCollectorImpl_klass); 14.25 + f->do_oop((oop*) &_gcInfo_klass); 14.26 } 14.27 14.28 klassOop Management::java_lang_management_ThreadInfo_klass(TRAPS) { 14.29 @@ -230,6 +235,20 @@ 14.30 return _managementFactory_klass; 14.31 } 14.32 14.33 +klassOop Management::sun_management_GarbageCollectorImpl_klass(TRAPS) { 14.34 + if (_garbageCollectorImpl_klass == NULL) { 14.35 + _garbageCollectorImpl_klass = load_and_initialize_klass(vmSymbols::sun_management_GarbageCollectorImpl(), CHECK_NULL); 14.36 + } 14.37 + return _garbageCollectorImpl_klass; 14.38 +} 14.39 + 14.40 +klassOop Management::com_sun_management_GcInfo_klass(TRAPS) { 14.41 + if (_gcInfo_klass == NULL) { 14.42 + _gcInfo_klass = load_and_initialize_klass(vmSymbols::com_sun_management_GcInfo(), CHECK_NULL); 14.43 + } 14.44 + return _gcInfo_klass; 14.45 +} 14.46 + 14.47 static void initialize_ThreadInfo_constructor_arguments(JavaCallArguments* args, ThreadSnapshot* snapshot, TRAPS) { 14.48 Handle snapshot_thread(THREAD, snapshot->threadObj()); 14.49 14.50 @@ -2056,6 +2075,13 @@ 14.51 } 14.52 JVM_END 14.53 14.54 +JVM_ENTRY(void, jmm_SetGCNotificationEnabled(JNIEnv *env, jobject obj, jboolean enabled)) 14.55 + ResourceMark rm(THREAD); 14.56 + // Get the GCMemoryManager 14.57 + GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK); 14.58 + mgr->set_notification_enabled(enabled?true:false); 14.59 +JVM_END 14.60 + 14.61 // Dump heap - Returns 0 if succeeds. 14.62 JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live)) 14.63 #ifndef SERVICES_KERNEL 14.64 @@ -2122,7 +2148,8 @@ 14.65 jmm_FindDeadlockedThreads, 14.66 jmm_SetVMGlobal, 14.67 NULL, 14.68 - jmm_DumpThreads 14.69 + jmm_DumpThreads, 14.70 + jmm_SetGCNotificationEnabled 14.71 }; 14.72 14.73 void* Management::get_jmm_interface(int version) {
15.1 --- a/src/share/vm/services/management.hpp Thu May 12 15:05:22 2011 -0700 15.2 +++ b/src/share/vm/services/management.hpp Thu May 12 17:36:45 2011 -0700 15.3 @@ -49,6 +49,8 @@ 15.4 static klassOop _memoryManagerMXBean_klass; 15.5 static klassOop _garbageCollectorMXBean_klass; 15.6 static klassOop _managementFactory_klass; 15.7 + static klassOop _garbageCollectorImpl_klass; 15.8 + static klassOop _gcInfo_klass; 15.9 15.10 static klassOop load_and_initialize_klass(Symbol* sh, TRAPS); 15.11 15.12 @@ -86,6 +88,8 @@ 15.13 static klassOop java_lang_management_GarbageCollectorMXBean_klass(TRAPS); 15.14 static klassOop sun_management_Sensor_klass(TRAPS); 15.15 static klassOop sun_management_ManagementFactory_klass(TRAPS); 15.16 + static klassOop sun_management_GarbageCollectorImpl_klass(TRAPS); 15.17 + static klassOop com_sun_management_GcInfo_klass(TRAPS); 15.18 15.19 static instanceOop create_thread_info_instance(ThreadSnapshot* snapshot, TRAPS); 15.20 static instanceOop create_thread_info_instance(ThreadSnapshot* snapshot, objArrayHandle monitors_array, typeArrayHandle depths_array, objArrayHandle synchronizers_array, TRAPS);
16.1 --- a/src/share/vm/services/memoryManager.cpp Thu May 12 15:05:22 2011 -0700 16.2 +++ b/src/share/vm/services/memoryManager.cpp Thu May 12 17:36:45 2011 -0700 16.3 @@ -33,6 +33,7 @@ 16.4 #include "services/memoryManager.hpp" 16.5 #include "services/memoryPool.hpp" 16.6 #include "services/memoryService.hpp" 16.7 +#include "services/gcNotifier.hpp" 16.8 #include "utilities/dtrace.hpp" 16.9 16.10 HS_DTRACE_PROBE_DECL8(hotspot, mem__pool__gc__begin, char*, int, char*, int, 16.11 @@ -202,6 +203,7 @@ 16.12 _last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true); 16.13 _current_gc_stat = NULL; 16.14 _num_gc_threads = 1; 16.15 + _notification_enabled = false; 16.16 } 16.17 16.18 GCMemoryManager::~GCMemoryManager() { 16.19 @@ -250,7 +252,8 @@ 16.20 // to ensure the current gc stat is placed in _last_gc_stat. 16.21 void GCMemoryManager::gc_end(bool recordPostGCUsage, 16.22 bool recordAccumulatedGCTime, 16.23 - bool recordGCEndTime, bool countCollection) { 16.24 + bool recordGCEndTime, bool countCollection, 16.25 + GCCause::Cause cause) { 16.26 if (recordAccumulatedGCTime) { 16.27 _accumulated_timer.stop(); 16.28 } 16.29 @@ -283,6 +286,11 @@ 16.30 pool->set_last_collection_usage(usage); 16.31 LowMemoryDetector::detect_after_gc_memory(pool); 16.32 } 16.33 + if(is_notification_enabled()) { 16.34 + bool isMajorGC = this == MemoryService::get_major_gc_manager(); 16.35 + GCNotifier::pushNotification(this, isMajorGC ? "end of major GC" : "end of minor GC", 16.36 + GCCause::to_string(cause)); 16.37 + } 16.38 } 16.39 if (countCollection) { 16.40 _num_collections++;
17.1 --- a/src/share/vm/services/memoryManager.hpp Thu May 12 15:05:22 2011 -0700 17.2 +++ b/src/share/vm/services/memoryManager.hpp Thu May 12 17:36:45 2011 -0700 17.3 @@ -166,6 +166,7 @@ 17.4 Mutex* _last_gc_lock; 17.5 GCStatInfo* _current_gc_stat; 17.6 int _num_gc_threads; 17.7 + volatile bool _notification_enabled; 17.8 public: 17.9 GCMemoryManager(); 17.10 ~GCMemoryManager(); 17.11 @@ -181,7 +182,7 @@ 17.12 void gc_begin(bool recordGCBeginTime, bool recordPreGCUsage, 17.13 bool recordAccumulatedGCTime); 17.14 void gc_end(bool recordPostGCUsage, bool recordAccumulatedGCTime, 17.15 - bool recordGCEndTime, bool countCollection); 17.16 + bool recordGCEndTime, bool countCollection, GCCause::Cause cause); 17.17 17.18 void reset_gc_stat() { _num_collections = 0; _accumulated_timer.reset(); } 17.19 17.20 @@ -189,6 +190,8 @@ 17.21 // the collection count. Zero signifies no gc has taken place. 17.22 size_t get_last_gc_stat(GCStatInfo* dest); 17.23 17.24 + void set_notification_enabled(bool enabled) { _notification_enabled = enabled; } 17.25 + bool is_notification_enabled() { return _notification_enabled; } 17.26 virtual MemoryManager::Name kind() = 0; 17.27 }; 17.28
18.1 --- a/src/share/vm/services/memoryService.cpp Thu May 12 15:05:22 2011 -0700 18.2 +++ b/src/share/vm/services/memoryService.cpp Thu May 12 17:36:45 2011 -0700 18.3 @@ -565,7 +565,8 @@ 18.4 18.5 void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage, 18.6 bool recordAccumulatedGCTime, 18.7 - bool recordGCEndTime, bool countCollection) { 18.8 + bool recordGCEndTime, bool countCollection, 18.9 + GCCause::Cause cause) { 18.10 18.11 GCMemoryManager* mgr; 18.12 if (fullGC) { 18.13 @@ -577,7 +578,7 @@ 18.14 18.15 // register the GC end statistics and memory usage 18.16 mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, 18.17 - countCollection); 18.18 + countCollection, cause); 18.19 } 18.20 18.21 void MemoryService::oops_do(OopClosure* f) { 18.22 @@ -633,7 +634,7 @@ 18.23 // gc manager (so _fullGC is set to false ) and for other generation kinds 18.24 // doing mark-sweep-compact uses major gc manager (so _fullGC is set 18.25 // to true). 18.26 -TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind) { 18.27 +TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause) { 18.28 switch (kind) { 18.29 case Generation::DefNew: 18.30 #ifndef SERIALGC 18.31 @@ -654,9 +655,10 @@ 18.32 } 18.33 // this has to be called in a stop the world pause and represent 18.34 // an entire gc pause, start to finish: 18.35 - initialize(_fullGC, true, true, true, true, true, true, true); 18.36 + initialize(_fullGC, cause,true, true, true, true, true, true, true); 18.37 } 18.38 TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC, 18.39 + GCCause::Cause cause, 18.40 bool recordGCBeginTime, 18.41 bool recordPreGCUsage, 18.42 bool recordPeakUsage, 18.43 @@ -664,7 +666,7 @@ 18.44 bool recordAccumulatedGCTime, 18.45 bool recordGCEndTime, 18.46 bool countCollection) { 18.47 - initialize(fullGC, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, 18.48 + initialize(fullGC, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, 18.49 recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, 18.50 countCollection); 18.51 } 18.52 @@ -672,6 +674,7 @@ 18.53 // for a subclass to create then initialize an instance before invoking 18.54 // the MemoryService 18.55 void TraceMemoryManagerStats::initialize(bool fullGC, 18.56 + GCCause::Cause cause, 18.57 bool recordGCBeginTime, 18.58 bool recordPreGCUsage, 18.59 bool recordPeakUsage, 18.60 @@ -687,6 +690,7 @@ 18.61 _recordAccumulatedGCTime = recordAccumulatedGCTime; 18.62 _recordGCEndTime = recordGCEndTime; 18.63 _countCollection = countCollection; 18.64 + _cause = cause; 18.65 18.66 MemoryService::gc_begin(_fullGC, _recordGCBeginTime, _recordAccumulatedGCTime, 18.67 _recordPreGCUsage, _recordPeakUsage); 18.68 @@ -694,6 +698,6 @@ 18.69 18.70 TraceMemoryManagerStats::~TraceMemoryManagerStats() { 18.71 MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime, 18.72 - _recordGCEndTime, _countCollection); 18.73 + _recordGCEndTime, _countCollection, _cause); 18.74 } 18.75
19.1 --- a/src/share/vm/services/memoryService.hpp Thu May 12 15:05:22 2011 -0700 19.2 +++ b/src/share/vm/services/memoryService.hpp Thu May 12 17:36:45 2011 -0700 19.3 @@ -29,6 +29,7 @@ 19.4 #include "memory/generation.hpp" 19.5 #include "runtime/handles.hpp" 19.6 #include "services/memoryUsage.hpp" 19.7 +#include "gc_interface/gcCause.hpp" 19.8 19.9 // Forward declaration 19.10 class MemoryPool; 19.11 @@ -162,7 +163,8 @@ 19.12 bool recordPreGCUsage, bool recordPeakUsage); 19.13 static void gc_end(bool fullGC, bool recordPostGCUsage, 19.14 bool recordAccumulatedGCTime, 19.15 - bool recordGCEndTime, bool countCollection); 19.16 + bool recordGCEndTime, bool countCollection, 19.17 + GCCause::Cause cause); 19.18 19.19 19.20 static void oops_do(OopClosure* f); 19.21 @@ -172,6 +174,14 @@ 19.22 19.23 // Create an instance of java/lang/management/MemoryUsage 19.24 static Handle create_MemoryUsage_obj(MemoryUsage usage, TRAPS); 19.25 + 19.26 + static const GCMemoryManager* get_minor_gc_manager() { 19.27 + return _minor_gc_manager; 19.28 + } 19.29 + 19.30 + static const GCMemoryManager* get_major_gc_manager() { 19.31 + return _major_gc_manager; 19.32 + } 19.33 }; 19.34 19.35 class TraceMemoryManagerStats : public StackObj { 19.36 @@ -184,10 +194,11 @@ 19.37 bool _recordAccumulatedGCTime; 19.38 bool _recordGCEndTime; 19.39 bool _countCollection; 19.40 - 19.41 + GCCause::Cause _cause; 19.42 public: 19.43 TraceMemoryManagerStats() {} 19.44 TraceMemoryManagerStats(bool fullGC, 19.45 + GCCause::Cause cause, 19.46 bool recordGCBeginTime = true, 19.47 bool recordPreGCUsage = true, 19.48 bool recordPeakUsage = true, 19.49 @@ -197,6 +208,7 @@ 19.50 bool countCollection = true); 19.51 19.52 void initialize(bool fullGC, 19.53 + GCCause::Cause cause, 19.54 bool recordGCBeginTime, 19.55 bool recordPreGCUsage, 19.56 bool recordPeakUsage, 19.57 @@ -205,7 +217,7 @@ 19.58 bool recordGCEndTime, 19.59 bool countCollection); 19.60 19.61 - TraceMemoryManagerStats(Generation::Name kind); 19.62 + TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause); 19.63 ~TraceMemoryManagerStats(); 19.64 }; 19.65