< prev index next >
src/hotspot/share/runtime/heapMonitoring.cpp
Print this page
rev 48551 : [mq]: heap8
rev 48552 : [mq]: heap10a
rev 48553 : [mq]: heap14_rebased
rev 48555 : [mq]: heap16
rev 48556 : [mq]: heap17
rev 48557 : [mq]: heap17
rev 48558 : [mq]: heap19
rev 48559 : [mq]: heap20
rev 48560 : [mq]: heap21
rev 48562 : [mq]: heap23
*** 24,53 ****
#include "precompiled.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "memory/universe.hpp"
#include "runtime/heapMonitoring.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/vframe.hpp"
static const int MaxStackDepth = 1024;
// Internal data structure representing traces, used when object has been GC'd.
class StackTraceData : public CHeapObj<mtInternal> {
private:
! jvmtiStackTrace* _trace;
int _references;
public:
! StackTraceData(jvmtiStackTrace* t) : _trace(t), _references(0) {}
void increment_reference_count() {
_references++;
}
! jvmtiStackTrace* get_trace() const {
return _trace;
}
static void unreference_and_free(StackTraceData* data) {
if (!data) {
--- 24,54 ----
#include "precompiled.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "memory/universe.hpp"
+ #include "prims/jvmtiEnvBase.hpp"
#include "runtime/heapMonitoring.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/vframe.hpp"
static const int MaxStackDepth = 1024;
// Internal data structure representing traces, used when object has been GC'd.
class StackTraceData : public CHeapObj<mtInternal> {
private:
! jvmtiAllocTraceInfo* _trace;
int _references;
public:
! StackTraceData(jvmtiAllocTraceInfo* t) : _trace(t), _references(0) {}
void increment_reference_count() {
_references++;
}
! jvmtiAllocTraceInfo* get_trace() const {
return _trace;
}
static void unreference_and_free(StackTraceData* data) {
if (!data) {
*** 55,65 ****
}
data->_references--;
if (data->_references == 0) {
if (data->_trace != NULL) {
! FREE_C_HEAP_ARRAY(jvmtiFrameInfo, data->_trace->frames);
FREE_C_HEAP_OBJ(data->_trace);
}
delete data;
}
}
--- 56,68 ----
}
data->_references--;
if (data->_references == 0) {
if (data->_trace != NULL) {
! jvmtiStackInfo* stack_info = data->_trace->stack_info;
! FREE_C_HEAP_ARRAY(jvmtiFrameInfo, stack_info->frame_buffer);
! FREE_C_HEAP_OBJ(stack_info);
FREE_C_HEAP_OBJ(data->_trace);
}
delete data;
}
}
*** 71,81 ****
class StackTraceDataWithOop : public StackTraceData {
private:
oop _obj;
public:
! StackTraceDataWithOop(jvmtiStackTrace* t, oop o) : StackTraceData(t) {
store_oop(o);
}
StackTraceDataWithOop() : StackTraceData(NULL), _obj(NULL) {
}
--- 74,84 ----
class StackTraceDataWithOop : public StackTraceData {
private:
oop _obj;
public:
! StackTraceDataWithOop(jvmtiAllocTraceInfo* t, oop o) : StackTraceData(t) {
store_oop(o);
}
StackTraceDataWithOop() : StackTraceData(NULL), _obj(NULL) {
}
*** 216,242 ****
// Each object that we profile is stored as trace with the thread_id.
class StackTraceStorage : public CHeapObj<mtInternal> {
public:
// The function that gets called to add a trace to the list of
// traces we are maintaining.
! void add_trace(jvmtiStackTrace* trace, oop o);
// The function that gets called by the client to retrieve the list
! // of stack traces. Passes a jvmtiStackTraces which will get mutated.
! void get_all_stack_traces(jvmtiStackTraces* traces);
// The function that gets called by the client to retrieve the list
! // of stack traces. Passes a jvmtiStackTraces which will get mutated.
! void get_garbage_stack_traces(jvmtiStackTraces* traces);
// The function that gets called by the client to retrieve the list
! // of stack traces. Passes a jvmtiStackTraces which will get mutated.
! void get_frequent_garbage_stack_traces(jvmtiStackTraces* traces);
// The function that gets called by the client to retrieve the list
! // of stack traces. Passes a jvmtiStackTraces which will get mutated.
! void get_cached_stack_traces(jvmtiStackTraces* traces);
// Executes whenever weak references are traversed. is_alive tells
// you if the given oop is still reachable and live.
void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
--- 219,253 ----
// Each object that we profile is stored as trace with the thread_id.
class StackTraceStorage : public CHeapObj<mtInternal> {
public:
// The function that gets called to add a trace to the list of
// traces we are maintaining.
! void add_trace(jvmtiAllocTraceInfo* trace, oop o);
// The function that gets called by the client to retrieve the list
! // of stack traces. Passes a jvmtiAllocTraceInfo which will get mutated.
! void get_all_stack_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr);
// The function that gets called by the client to retrieve the list
! // of stack traces. Passes a jvmtiAllocTraceInfo which will get mutated.
! void get_garbage_stack_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr);
// The function that gets called by the client to retrieve the list
! // of stack traces. Passes a jvmtiAllocTraceInfo which will get mutated.
! void get_frequent_garbage_stack_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr);
// The function that gets called by the client to retrieve the list
! // of stack traces. Passes a jvmtiAllocTraceInfo which will get mutated.
! void get_cached_stack_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr);
// Executes whenever weak references are traversed. is_alive tells
// you if the given oop is still reachable and live.
void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
*** 269,278 ****
--- 280,290 ----
_stats.sample_rate_count++;
}
bool initialized() {
return OrderAccess::load_acquire(&_initialized) != 0;
+ return _initialized;
}
private:
// The traces currently sampled.
GrowableArray<StackTraceDataWithOop>* _allocated_traces;
*** 324,347 ****
private:
StackTraceData** _data;
int _size;
};
- // Copies from StackTraceData to jvmtiStackTrace.
- bool deep_copy(jvmtiStackTrace* to, const StackTraceData* from);
-
// Creates a deep copy of the list of StackTraceData.
! void copy_stack_traces(const StackTraceDataCopier &copier,
! jvmtiStackTraces* traces);
void store_garbage_trace(const StackTraceDataWithOop &trace);
void free_garbage();
void free_storage();
void reset();
void allocate_storage(int max_gc_storage);
};
StackTraceStorage* StackTraceStorage::internal_storage;
// Statics for Sampler
--- 336,372 ----
private:
StackTraceData** _data;
int _size;
};
// Creates a deep copy of the list of StackTraceData.
! void copy_stack_traces(JvmtiEnv* env,
! const StackTraceDataCopier &copier,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr);
void store_garbage_trace(const StackTraceDataWithOop &trace);
void free_garbage();
void free_storage();
void reset();
void allocate_storage(int max_gc_storage);
+
+ int calculate_frame_count(const StackTraceDataCopier &copier);
+ int calculate_info_count(const StackTraceDataCopier &copier);
+
+ bool copy_frame(const StackTraceData* stack_trace_data,
+ jvmtiAllocTraceInfo* current_alloc_traces,
+ jvmtiStackInfo* current_stack_info,
+ jvmtiFrameInfo* current_frame_info);
+
+ // Returns frame copy success. Failure can result when there is no longer
+ // enough memory.
+ bool copy_frames(const StackTraceDataCopier& copier, int info_count,
+ unsigned char* start,
+ unsigned char* end);
};
StackTraceStorage* StackTraceStorage::internal_storage;
// Statics for Sampler
*** 351,364 ****
--- 376,394 ----
// Cheap random number generator
uint64_t HeapMonitoring::_rnd;
StackTraceStorage::StackTraceStorage() {
+ MutexLocker mu(HeapMonitorStorage_lock);
reset();
}
void StackTraceStorage::reset() {
+ assert(HeapMonitorStorage_lock->owned_by_self()
+ || (SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread()),
+ "This should not be accessed concurrently");
+
_allocated_traces = NULL;
_traces_on_last_full_gc = NULL;
_recent_garbage_traces = NULL;
_frequent_garbage_traces = NULL;
_max_gc_storage = 0;
*** 413,422 ****
--- 443,456 ----
MutexLocker mu(HeapMonitorStorage_lock);
free_storage();
}
void StackTraceStorage::allocate_storage(int max_gc_storage) {
+ assert(HeapMonitorStorage_lock->owned_by_self()
+ || (SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread()),
+ "This should not be accessed concurrently");
+
// In case multiple threads got locked and then 1 by 1 got through.
if (initialized()) {
return;
}
*** 431,449 ****
_max_gc_storage = max_gc_storage;
memset(&_stats, 0, sizeof(_stats));
OrderAccess::release_store(&_initialized, 1);
}
! void StackTraceStorage::add_trace(jvmtiStackTrace* trace, oop o) {
MutexLocker mu(HeapMonitorStorage_lock);
// Last minute check on initialization here in case:
// Between the moment object_alloc_do_sample's check for initialization
// and now, there was a stop() that deleted the data.
if (initialized()) {
StackTraceDataWithOop new_data(trace, o);
_stats.sample_count++;
! _stats.stack_depth_accumulation += trace->frame_count;
_allocated_traces->append(new_data);
}
}
void StackTraceStorage::weak_oops_do(BoolObjectClosure* is_alive,
--- 465,483 ----
_max_gc_storage = max_gc_storage;
memset(&_stats, 0, sizeof(_stats));
OrderAccess::release_store(&_initialized, 1);
}
! void StackTraceStorage::add_trace(jvmtiAllocTraceInfo* trace, oop o) {
MutexLocker mu(HeapMonitorStorage_lock);
// Last minute check on initialization here in case:
// Between the moment object_alloc_do_sample's check for initialization
// and now, there was a stop() that deleted the data.
if (initialized()) {
StackTraceDataWithOop new_data(trace, o);
_stats.sample_count++;
! _stats.stack_depth_accumulation += trace->stack_info->frame_count;
_allocated_traces->append(new_data);
}
}
void StackTraceStorage::weak_oops_do(BoolObjectClosure* is_alive,
*** 489,604 ****
}
log_develop_trace(gc, ref)("Clearing HeapMonitoring weak reference (" INT64_FORMAT ")", count);
}
- bool StackTraceStorage::deep_copy(jvmtiStackTrace* to,
- const StackTraceData* from) {
- const jvmtiStackTrace* src = from->get_trace();
- *to = *src;
-
- to->frames =
- NEW_C_HEAP_ARRAY(jvmtiFrameInfo, src->frame_count, mtInternal);
-
- if (to->frames == NULL) {
- return false;
- }
-
- memcpy(to->frames,
- src->frames,
- sizeof(jvmtiFrameInfo) * src->frame_count);
- return true;
- }
-
// Called by the outside world; returns a copy of the stack traces
// (because we could be replacing them as the user handles them).
// The array is secretly null-terminated (to make it easier to reclaim).
! void StackTraceStorage::get_all_stack_traces(jvmtiStackTraces* traces) {
MutexLocker mu(HeapMonitorStorage_lock);
if (!_allocated_traces) {
! traces->stack_traces = NULL;
! traces->trace_count = 0;
return;
}
LiveStackTraceDataCopier copier(_allocated_traces);
! copy_stack_traces(copier, traces);
}
// See comment on get_all_stack_traces
! void StackTraceStorage::get_garbage_stack_traces(jvmtiStackTraces* traces) {
MutexLocker mu(HeapMonitorStorage_lock);
if (!_recent_garbage_traces) {
! traces->stack_traces = NULL;
! traces->trace_count = 0;
return;
}
GarbageStackTraceDataCopier copier(_recent_garbage_traces->get_traces(),
_recent_garbage_traces->size());
! copy_stack_traces(copier, traces);
}
// See comment on get_all_stack_traces
void StackTraceStorage::get_frequent_garbage_stack_traces(
! jvmtiStackTraces* traces) {
MutexLocker mu(HeapMonitorStorage_lock);
if (!_frequent_garbage_traces) {
! traces->stack_traces = NULL;
! traces->trace_count = 0;
return;
}
GarbageStackTraceDataCopier copier(_frequent_garbage_traces->get_traces(),
_frequent_garbage_traces->size());
! copy_stack_traces(copier, traces);
}
// See comment on get_all_stack_traces
! void StackTraceStorage::get_cached_stack_traces(jvmtiStackTraces* traces) {
MutexLocker mu(HeapMonitorStorage_lock);
if (!_traces_on_last_full_gc) {
! traces->stack_traces = NULL;
! traces->trace_count = 0;
return;
}
LiveStackTraceDataCopier copier(_traces_on_last_full_gc);
! copy_stack_traces(copier, traces);
}
! void StackTraceStorage::copy_stack_traces(const StackTraceDataCopier &copier,
! jvmtiStackTraces* traces) {
int len = copier.size();
! // Create a new array to store the StackTraceData objects.
! // + 1 for a NULL at the end.
! jvmtiStackTrace* t =
! NEW_C_HEAP_ARRAY(jvmtiStackTrace, len + 1, mtInternal);
! if (t == NULL) {
! traces->stack_traces = NULL;
! traces->trace_count = 0;
! return;
}
- // +1 to have a NULL at the end of the array.
- memset(t, 0, (len + 1) * sizeof(*t));
! // Copy the StackTraceData objects into the new array.
! int trace_count = 0;
for (int i = 0; i < len; i++) {
const StackTraceData* stack_trace = copier.get(i);
if (stack_trace != NULL) {
! jvmtiStackTrace* to = &t[trace_count];
! if (!deep_copy(to, stack_trace)) {
! continue;
}
! trace_count++;
}
}
! traces->stack_traces = t;
! traces->trace_count = trace_count;
}
void StackTraceStorage::store_garbage_trace(const StackTraceDataWithOop &trace) {
StackTraceData* new_trace = new StackTraceData(trace.get_trace());
--- 523,727 ----
}
log_develop_trace(gc, ref)("Clearing HeapMonitoring weak reference (" INT64_FORMAT ")", count);
}
// Called by the outside world; returns a copy of the stack traces
// (because we could be replacing them as the user handles them).
// The array is secretly null-terminated (to make it easier to reclaim).
! void StackTraceStorage::get_all_stack_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr) {
MutexLocker mu(HeapMonitorStorage_lock);
if (!_allocated_traces) {
! *traces = NULL;
! *trace_counter_ptr = 0;
return;
}
LiveStackTraceDataCopier copier(_allocated_traces);
! copy_stack_traces(env, copier, traces, trace_counter_ptr);
}
// See comment on get_all_stack_traces
! void StackTraceStorage::get_garbage_stack_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr) {
MutexLocker mu(HeapMonitorStorage_lock);
if (!_recent_garbage_traces) {
! *traces = NULL;
! *trace_counter_ptr = 0;
return;
}
GarbageStackTraceDataCopier copier(_recent_garbage_traces->get_traces(),
_recent_garbage_traces->size());
! copy_stack_traces(env, copier, traces, trace_counter_ptr);
}
// See comment on get_all_stack_traces
void StackTraceStorage::get_frequent_garbage_stack_traces(
! JvmtiEnv* env, jvmtiAllocTraceInfo** traces, jint* trace_counter_ptr) {
MutexLocker mu(HeapMonitorStorage_lock);
if (!_frequent_garbage_traces) {
! *traces = NULL;
! *trace_counter_ptr = 0;
return;
}
GarbageStackTraceDataCopier copier(_frequent_garbage_traces->get_traces(),
_frequent_garbage_traces->size());
! copy_stack_traces(env, copier, traces, trace_counter_ptr);
}
// See comment on get_all_stack_traces
! void StackTraceStorage::get_cached_stack_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr) {
MutexLocker mu(HeapMonitorStorage_lock);
if (!_traces_on_last_full_gc) {
! *traces = NULL;
! *trace_counter_ptr = 0;
return;
}
LiveStackTraceDataCopier copier(_traces_on_last_full_gc);
! copy_stack_traces(env, copier, traces, trace_counter_ptr);
}
! int StackTraceStorage::calculate_frame_count(const StackTraceDataCopier &copier) {
int len = copier.size();
! // Walk the traces first to find the size of the frames as well.
! int frame_total = 0;
!
! for (int i = 0; i < len; i++) {
! const StackTraceData* stack_trace = copier.get(i);
!
! if (stack_trace != NULL) {
! jvmtiAllocTraceInfo* trace = stack_trace->get_trace();
! jvmtiStackInfo* stack_info = trace->stack_info;
! frame_total += stack_info->frame_count;
! }
}
! return frame_total;
! }
!
! int StackTraceStorage::calculate_info_count(const StackTraceDataCopier &copier) {
! int len = copier.size();
!
! int info_total = 0;
!
for (int i = 0; i < len; i++) {
const StackTraceData* stack_trace = copier.get(i);
+
if (stack_trace != NULL) {
! // TODO: merge this with the method above.
! info_total++;
! }
! }
!
! return info_total;
! }
!
! // Method to test if the data structure would fit between the src address and
! // the end address.
! template<typename T, typename U>
! static bool next_ptr_less_or_equal(T src, U* end) {
! return (src + 1) <= reinterpret_cast<T>(end);
! }
!
! bool StackTraceStorage::copy_frame(const StackTraceData* stack_trace_data,
! jvmtiAllocTraceInfo* current_alloc_trace,
! jvmtiStackInfo* current_stack_info,
! jvmtiFrameInfo* current_frame_info) {
! jvmtiAllocTraceInfo* trace = stack_trace_data->get_trace();
! jvmtiStackInfo* stack_info = trace->stack_info;
! int frame_count = stack_info->frame_count;
!
! memcpy(current_alloc_trace, trace, sizeof(*trace));
!
! current_alloc_trace->stack_info = current_stack_info;
! memcpy(current_stack_info, stack_info, sizeof(*stack_info));
!
! current_stack_info->frame_buffer = current_frame_info;
! memcpy(current_frame_info, stack_info->frame_buffer,
! sizeof(jvmtiFrameInfo) * frame_count);
! return true;
! }
!
! bool StackTraceStorage::copy_frames(const StackTraceDataCopier& copier,
! int info_count,
! unsigned char* start,
! unsigned char* end) {
! jvmtiAllocTraceInfo* start_alloc_trace = reinterpret_cast<jvmtiAllocTraceInfo*>(start);
! jvmtiStackInfo* start_stack_info = reinterpret_cast<jvmtiStackInfo*>(start_alloc_trace + info_count);
! jvmtiFrameInfo* start_frame_info = reinterpret_cast<jvmtiFrameInfo*>(start_stack_info + info_count);
!
! jvmtiAllocTraceInfo* current_alloc_trace = start_alloc_trace;
! jvmtiStackInfo* current_stack_info = start_stack_info;
! jvmtiFrameInfo* current_frame_info = start_frame_info;
!
! for (int i = 0; i < info_count; i++) {
! assert(next_ptr_less_or_equal(current_alloc_trace, start_stack_info),
! "jvmtiAllocTraceInfo would write over jvmtiStackInfos.");
! assert(next_ptr_less_or_equal(current_stack_info, start_frame_info),
! "jvmtiStackInfo would write over jvmtiFrameInfos.");
!
! assert(next_ptr_less_or_equal(current_frame_info, end),
! "jvmtiFrameInfo would write over the end of the buffer.");
!
! const StackTraceData* stack_trace_data = copier.get(i);
! if (stack_trace_data != NULL) {
! if (!copy_frame(stack_trace_data, current_alloc_trace,
! current_stack_info, current_frame_info)) {
! return false;
}
!
! current_frame_info += current_stack_info->frame_count;
! current_stack_info++;
! current_alloc_trace++;
}
}
! return true;
! }
!
! void StackTraceStorage::copy_stack_traces(JvmtiEnv* env,
! const StackTraceDataCopier& copier,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr) {
! *traces = NULL;
! *trace_counter_ptr = 0;
!
! int frame_total = calculate_frame_count(copier);
! int len = calculate_info_count(copier);
!
! // Allocate the whole stacktraces in one bloc to simplify freeing.
! size_t total_size = len * sizeof(jvmtiAllocTraceInfo)
! + len * sizeof(jvmtiStackInfo)
! + frame_total * sizeof(jvmtiFrameInfo);
!
! unsigned char* buffer = NULL;
! jvmtiAllocTraceInfo* result = NULL;
! JvmtiEnvBase* env_base = reinterpret_cast<JvmtiEnvBase*>(env);
! env_base->allocate(total_size, &buffer);
!
! if (buffer == NULL) {
! return;
! }
!
! bool success = copy_frames(copier, len, buffer, buffer + total_size);
!
! if (!success) {
! env_base->deallocate(buffer);
! return;
! }
!
! *trace_counter_ptr = len;
! *traces = reinterpret_cast<jvmtiAllocTraceInfo*>(buffer);
}
void StackTraceStorage::store_garbage_trace(const StackTraceDataWithOop &trace) {
StackTraceData* new_trace = new StackTraceData(trace.get_trace());
*** 613,656 ****
}
_stats.garbage_collected_samples++;
}
! void HeapMonitoring::get_live_traces(jvmtiStackTraces* traces) {
! StackTraceStorage::storage()->get_all_stack_traces(traces);
}
void HeapMonitoring::get_sampling_statistics(jvmtiHeapSamplingStats* stats) {
const jvmtiHeapSamplingStats& internal_stats =
StackTraceStorage::storage()->get_heap_sampling_stats();
*stats = internal_stats;
}
! void HeapMonitoring::get_frequent_garbage_traces(jvmtiStackTraces* traces) {
! StackTraceStorage::storage()->get_frequent_garbage_stack_traces(traces);
! }
!
! void HeapMonitoring::get_garbage_traces(jvmtiStackTraces* traces) {
! StackTraceStorage::storage()->get_garbage_stack_traces(traces);
! }
!
! void HeapMonitoring::get_cached_traces(jvmtiStackTraces* traces) {
! StackTraceStorage::storage()->get_cached_stack_traces(traces);
! }
!
! void HeapMonitoring::release_traces(jvmtiStackTraces* traces) {
! jint trace_count = traces->trace_count;
! jvmtiStackTrace* stack_traces = traces->stack_traces;
!
! for (jint i = 0; i < trace_count; i++) {
! jvmtiStackTrace* current_trace = stack_traces + i;
! FREE_C_HEAP_ARRAY(jvmtiFrameInfo, current_trace->frames);
! }
!
! FREE_C_HEAP_ARRAY(jvmtiStackTrace, traces->stack_traces);
! traces->trace_count = 0;
! traces->stack_traces = NULL;
}
// Invoked by the GC to clean up old stack traces and remove old arrays
// of instrumentation that are still lying around.
void HeapMonitoring::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
--- 736,780 ----
}
_stats.garbage_collected_samples++;
}
! void HeapMonitoring::get_live_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr) {
! StackTraceStorage::storage()->get_all_stack_traces(env,
! traces,
! trace_counter_ptr);
}
void HeapMonitoring::get_sampling_statistics(jvmtiHeapSamplingStats* stats) {
const jvmtiHeapSamplingStats& internal_stats =
StackTraceStorage::storage()->get_heap_sampling_stats();
*stats = internal_stats;
}
! void HeapMonitoring::get_frequent_garbage_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr) {
! StackTraceStorage::storage()->get_frequent_garbage_stack_traces(
! env, traces, trace_counter_ptr);
! }
!
! void HeapMonitoring::get_garbage_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr) {
! StackTraceStorage::storage()->get_garbage_stack_traces(env,
! traces,
! trace_counter_ptr);
! }
!
! void HeapMonitoring::get_cached_traces(JvmtiEnv* env,
! jvmtiAllocTraceInfo** traces,
! jint* trace_counter_ptr) {
! StackTraceStorage::storage()->get_cached_stack_traces(env,
! traces,
! trace_counter_ptr);
}
// Invoked by the GC to clean up old stack traces and remove old arrays
// of instrumentation that are still lying around.
void HeapMonitoring::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
*** 729,761 ****
*ptr = rate;
StackTraceStorage::storage()->accumulate_sample_rate(rate);
}
! void HeapMonitoring::object_alloc_do_sample(Thread* t, oopDesc* o, intx byte_size) {
JavaThread* thread = static_cast<JavaThread*>(t);
if (StackTraceStorage::storage()->initialized()) {
assert(t->is_Java_thread(), "non-Java thread passed to do_sample");
JavaThread* thread = static_cast<JavaThread*>(t);
! jvmtiStackTrace* trace = NEW_C_HEAP_OBJ(jvmtiStackTrace, mtInternal);
if (trace == NULL) {
return;
}
jvmtiFrameInfo* frames =
NEW_C_HEAP_ARRAY(jvmtiFrameInfo, MaxStackDepth, mtInternal);
if (frames == NULL) {
FREE_C_HEAP_OBJ(trace);
return;
}
- trace->frames = frames;
trace->thread_id = SharedRuntime::get_java_tid(thread);
trace->size = byte_size;
- trace->frame_count = 0;
if (thread->has_last_Java_frame()) { // just to be safe
vframeStream vfst(thread, true);
int count = 0;
while (!vfst.at_end() && count < MaxStackDepth) {
--- 853,893 ----
*ptr = rate;
StackTraceStorage::storage()->accumulate_sample_rate(rate);
}
! void HeapMonitoring::object_alloc_do_sample(Thread* t, oopDesc* o, size_t byte_size) {
JavaThread* thread = static_cast<JavaThread*>(t);
if (StackTraceStorage::storage()->initialized()) {
assert(t->is_Java_thread(), "non-Java thread passed to do_sample");
JavaThread* thread = static_cast<JavaThread*>(t);
! jvmtiAllocTraceInfo* trace = NEW_C_HEAP_OBJ(jvmtiAllocTraceInfo, mtInternal);
! if (trace == NULL) {
! return;
! }
!
! jvmtiStackInfo* stack_info = NEW_C_HEAP_OBJ(jvmtiStackInfo, mtInternal);
if (trace == NULL) {
+ FREE_C_HEAP_OBJ(trace);
return;
}
+ trace->stack_info = stack_info;
jvmtiFrameInfo* frames =
NEW_C_HEAP_ARRAY(jvmtiFrameInfo, MaxStackDepth, mtInternal);
if (frames == NULL) {
+ FREE_C_HEAP_OBJ(stack_info);
FREE_C_HEAP_OBJ(trace);
return;
}
+ stack_info->frame_buffer = frames;
+ stack_info->frame_count = 0;
trace->thread_id = SharedRuntime::get_java_tid(thread);
trace->size = byte_size;
if (thread->has_last_Java_frame()) { // just to be safe
vframeStream vfst(thread, true);
int count = 0;
while (!vfst.at_end() && count < MaxStackDepth) {
*** 764,782 ****
frames[count].method = m->jmethod_id();
count++;
vfst.next();
}
! trace->frame_count = count;
}
! if (trace->frame_count> 0) {
// Success!
StackTraceStorage::storage()->add_trace(trace, o);
return;
}
// Failure!
! FREE_C_HEAP_ARRAY(jvmtiFrameInfo, trace->frames);
FREE_C_HEAP_OBJ(trace);
}
}
--- 896,915 ----
frames[count].method = m->jmethod_id();
count++;
vfst.next();
}
! stack_info->frame_count = count;
}
! if (stack_info->frame_count > 0) {
// Success!
StackTraceStorage::storage()->add_trace(trace, o);
return;
}
// Failure!
! FREE_C_HEAP_ARRAY(jvmtiFrameInfo, frames);
! FREE_C_HEAP_OBJ(stack_info);
FREE_C_HEAP_OBJ(trace);
}
}
< prev index next >