1 /* 2 * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP 26 #define SHARE_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP 27 28 #include "jfr/utilities/jfrAllocation.hpp" 29 #include "jfr/utilities/jfrBlob.hpp" 30 #include "jfr/utilities/jfrTime.hpp" 31 #include "jfr/utilities/jfrTypes.hpp" 32 #include "memory/allocation.hpp" 33 #include "oops/oop.hpp" 34 #include "utilities/ticks.hpp" 35 36 /* 37 * Handle for diagnosing Java memory leaks. 38 * 39 * The class tracks the time the object was 40 * allocated, the thread and the stack trace. 41 */ 42 class ObjectSample : public JfrCHeapObj { 43 friend class ObjectSampler; 44 friend class SampleList; 45 private: 46 ObjectSample* _next; 47 ObjectSample* _previous; 48 JfrBlobHandle _stacktrace; 49 JfrBlobHandle _thread; 50 JfrBlobHandle _type_set; 51 oop _object; 52 Ticks _allocation_time; 53 traceid _stack_trace_id; 54 traceid _thread_id; 55 int _index; 56 size_t _span; 57 size_t _allocated; 58 size_t _heap_used_at_last_gc; 59 unsigned int _stack_trace_hash; 60 release_references()61 void release_references() { 62 _stacktrace.~JfrBlobHandle(); 63 _thread.~JfrBlobHandle(); 64 _type_set.~JfrBlobHandle(); 65 } 66 reset()67 void reset() { 68 _object = NULL; 69 set_stack_trace_id(0); 70 set_stack_trace_hash(0); 71 release_references(); 72 } 73 74 public: ObjectSample()75 ObjectSample() : _next(NULL), 76 _previous(NULL), 77 _stacktrace(), 78 _thread(), 79 _type_set(), 80 _object(NULL), 81 _allocation_time(), 82 _stack_trace_id(0), 83 _thread_id(0), 84 _index(0), 85 _span(0), 86 _allocated(0), 87 _heap_used_at_last_gc(0), 88 _stack_trace_hash(0) {} 89 next() const90 ObjectSample* next() const { 91 return _next; 92 } 93 set_next(ObjectSample * next)94 void set_next(ObjectSample* next) { 95 _next = next; 96 } 97 prev() const98 ObjectSample* prev() const { 99 return _previous; 100 } 101 set_prev(ObjectSample * prev)102 void set_prev(ObjectSample* prev) { 103 _previous = prev; 104 } 105 is_dead() const106 bool is_dead() const { 107 return object() == NULL; 108 } 109 110 const oop object() const; 111 void set_object(oop object); 112 object_addr() const113 const oop* object_addr() const { 114 return &_object; 115 } 116 index() const117 int index() const { 118 return _index; 119 } 120 set_index(int index)121 void set_index(int index) { 122 _index = index; 123 } 124 span() const125 size_t span() const { 126 return _span; 127 } 128 set_span(size_t span)129 void set_span(size_t span) { 130 _span = span; 131 } 132 add_span(size_t span)133 void add_span(size_t span) { 134 _span += span; 135 } 136 allocated() const137 size_t allocated() const { 138 return _allocated; 139 } 140 set_allocated(size_t size)141 void set_allocated(size_t size) { 142 _allocated = size; 143 } 144 allocation_time() const145 const Ticks& allocation_time() const { 146 return _allocation_time; 147 } 148 set_allocation_time(const JfrTicks & time)149 const void set_allocation_time(const JfrTicks& time) { 150 _allocation_time = Ticks(time.value()); 151 } 152 set_heap_used_at_last_gc(size_t heap_used)153 void set_heap_used_at_last_gc(size_t heap_used) { 154 _heap_used_at_last_gc = heap_used; 155 } 156 heap_used_at_last_gc() const157 size_t heap_used_at_last_gc() const { 158 return _heap_used_at_last_gc; 159 } 160 has_stack_trace_id() const161 bool has_stack_trace_id() const { 162 return stack_trace_id() != 0; 163 } 164 stack_trace_id() const165 traceid stack_trace_id() const { 166 return _stack_trace_id; 167 } 168 set_stack_trace_id(traceid id)169 void set_stack_trace_id(traceid id) { 170 _stack_trace_id = id; 171 } 172 stack_trace_hash() const173 unsigned int stack_trace_hash() const { 174 return _stack_trace_hash; 175 } 176 set_stack_trace_hash(unsigned int hash)177 void set_stack_trace_hash(unsigned int hash) { 178 _stack_trace_hash = hash; 179 } 180 thread_id() const181 traceid thread_id() const { 182 return _thread_id; 183 } 184 set_thread_id(traceid id)185 void set_thread_id(traceid id) { 186 _thread_id = id; 187 } 188 is_alive_and_older_than(jlong time_stamp) const189 bool is_alive_and_older_than(jlong time_stamp) const { 190 return !is_dead() && (JfrTime::is_ft_enabled() ? 191 _allocation_time.ft_value() : _allocation_time.value()) < time_stamp; 192 } 193 stacktrace() const194 const JfrBlobHandle& stacktrace() const { 195 return _stacktrace; 196 } 197 has_stacktrace() const198 bool has_stacktrace() const { 199 return _stacktrace.valid(); 200 } 201 202 // JfrBlobHandle assignment operator 203 // maintains proper reference counting set_stacktrace(const JfrBlobHandle & ref)204 void set_stacktrace(const JfrBlobHandle& ref) { 205 if (_stacktrace != ref) { 206 _stacktrace = ref; 207 } 208 } 209 thread() const210 const JfrBlobHandle& thread() const { 211 return _thread; 212 } 213 has_thread() const214 bool has_thread() const { 215 return _thread.valid(); 216 } 217 set_thread(const JfrBlobHandle & ref)218 void set_thread(const JfrBlobHandle& ref) { 219 if (_thread != ref) { 220 _thread = ref; 221 } 222 } 223 type_set() const224 const JfrBlobHandle& type_set() const { 225 return _type_set; 226 } 227 has_type_set() const228 bool has_type_set() const { 229 return _type_set.valid(); 230 } 231 set_type_set(const JfrBlobHandle & ref)232 void set_type_set(const JfrBlobHandle& ref) { 233 if (_type_set != ref) { 234 if (_type_set.valid()) { 235 _type_set->set_next(ref); 236 return; 237 } 238 _type_set = ref; 239 } 240 } 241 }; 242 243 #endif // SHARE_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP 244