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 bool _dead; 61 set_dead()62 void set_dead() { 63 _dead = true; 64 } 65 release_references()66 void release_references() { 67 _stacktrace.~JfrBlobHandle(); 68 _thread.~JfrBlobHandle(); 69 _type_set.~JfrBlobHandle(); 70 } 71 reset()72 void reset() { 73 set_stack_trace_id(0); 74 set_stack_trace_hash(0); 75 release_references(); 76 _dead = false; 77 } 78 79 public: ObjectSample()80 ObjectSample() : _next(NULL), 81 _previous(NULL), 82 _stacktrace(), 83 _thread(), 84 _type_set(), 85 _object(NULL), 86 _allocation_time(), 87 _stack_trace_id(0), 88 _thread_id(0), 89 _index(0), 90 _span(0), 91 _allocated(0), 92 _heap_used_at_last_gc(0), 93 _stack_trace_hash(0), 94 _dead(false) {} 95 next() const96 ObjectSample* next() const { 97 return _next; 98 } 99 set_next(ObjectSample * next)100 void set_next(ObjectSample* next) { 101 _next = next; 102 } 103 prev() const104 ObjectSample* prev() const { 105 return _previous; 106 } 107 set_prev(ObjectSample * prev)108 void set_prev(ObjectSample* prev) { 109 _previous = prev; 110 } 111 is_dead() const112 bool is_dead() const { 113 return _dead; 114 } 115 object() const116 const oop object() const { 117 return _object; 118 } 119 object_addr() const120 const oop* object_addr() const { 121 return &_object; 122 } 123 set_object(oop object)124 void set_object(oop object) { 125 _object = object; 126 } 127 klass() const128 const Klass* klass() const { 129 assert(_object != NULL, "invariant"); 130 return _object->klass(); 131 } 132 index() const133 int index() const { 134 return _index; 135 } 136 set_index(int index)137 void set_index(int index) { 138 _index = index; 139 } 140 span() const141 size_t span() const { 142 return _span; 143 } 144 set_span(size_t span)145 void set_span(size_t span) { 146 _span = span; 147 } 148 add_span(size_t span)149 void add_span(size_t span) { 150 _span += span; 151 } 152 allocated() const153 size_t allocated() const { 154 return _allocated; 155 } 156 set_allocated(size_t size)157 void set_allocated(size_t size) { 158 _allocated = size; 159 } 160 allocation_time() const161 const Ticks& allocation_time() const { 162 return _allocation_time; 163 } 164 set_allocation_time(const JfrTicks & time)165 const void set_allocation_time(const JfrTicks& time) { 166 _allocation_time = Ticks(time.value()); 167 } 168 set_heap_used_at_last_gc(size_t heap_used)169 void set_heap_used_at_last_gc(size_t heap_used) { 170 _heap_used_at_last_gc = heap_used; 171 } 172 heap_used_at_last_gc() const173 size_t heap_used_at_last_gc() const { 174 return _heap_used_at_last_gc; 175 } 176 has_stack_trace_id() const177 bool has_stack_trace_id() const { 178 return stack_trace_id() != 0; 179 } 180 stack_trace_id() const181 traceid stack_trace_id() const { 182 return _stack_trace_id; 183 } 184 set_stack_trace_id(traceid id)185 void set_stack_trace_id(traceid id) { 186 _stack_trace_id = id; 187 } 188 stack_trace_hash() const189 unsigned int stack_trace_hash() const { 190 return _stack_trace_hash; 191 } 192 set_stack_trace_hash(unsigned int hash)193 void set_stack_trace_hash(unsigned int hash) { 194 _stack_trace_hash = hash; 195 } 196 thread_id() const197 traceid thread_id() const { 198 return _thread_id; 199 } 200 set_thread_id(traceid id)201 void set_thread_id(traceid id) { 202 _thread_id = id; 203 } 204 is_alive_and_older_than(jlong time_stamp) const205 bool is_alive_and_older_than(jlong time_stamp) const { 206 return !is_dead() && (JfrTime::is_ft_enabled() ? 207 _allocation_time.ft_value() : _allocation_time.value()) < time_stamp; 208 } 209 stacktrace() const210 const JfrBlobHandle& stacktrace() const { 211 return _stacktrace; 212 } 213 has_stacktrace() const214 bool has_stacktrace() const { 215 return _stacktrace.valid(); 216 } 217 218 // JfrBlobHandle assignment operator 219 // maintains proper reference counting set_stacktrace(const JfrBlobHandle & ref)220 void set_stacktrace(const JfrBlobHandle& ref) { 221 if (_stacktrace != ref) { 222 _stacktrace = ref; 223 } 224 } 225 thread() const226 const JfrBlobHandle& thread() const { 227 return _thread; 228 } 229 has_thread() const230 bool has_thread() const { 231 return _thread.valid(); 232 } 233 set_thread(const JfrBlobHandle & ref)234 void set_thread(const JfrBlobHandle& ref) { 235 if (_thread != ref) { 236 _thread = ref; 237 } 238 } 239 type_set() const240 const JfrBlobHandle& type_set() const { 241 return _type_set; 242 } 243 has_type_set() const244 bool has_type_set() const { 245 return _type_set.valid(); 246 } 247 set_type_set(const JfrBlobHandle & ref)248 void set_type_set(const JfrBlobHandle& ref) { 249 if (_type_set != ref) { 250 if (_type_set.valid()) { 251 _type_set->set_next(ref); 252 return; 253 } 254 _type_set = ref; 255 } 256 } 257 }; 258 259 #endif // SHARE_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP 260