1 /* 2 * Copyright (c) 2014, 2018, 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_VM_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP 26 #define SHARE_VM_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP 27 28 #include "jfr/recorder/checkpoint/jfrCheckpointBlob.hpp" 29 #include "jfr/utilities/jfrAllocation.hpp" 30 #include "jfr/utilities/jfrTraceTime.hpp" 31 #include "memory/allocation.hpp" 32 #include "oops/oop.hpp" 33 #include "trace/tracing.hpp" 34 #include "utilities/ticks.hpp" 35 /* 36 * Handle for diagnosing Java memory leaks. 37 * 38 * The class tracks the time the object was 39 * allocated, the thread and the stack trace. 40 */ 41 class ObjectSample : public JfrCHeapObj { 42 friend class ObjectSampler; 43 friend class SampleList; 44 private: 45 ObjectSample* _next; 46 ObjectSample* _previous; 47 JfrCheckpointBlobHandle _thread_cp; 48 JfrCheckpointBlobHandle _klass_cp; 49 oop _object; 50 Ticks _allocation_time; 51 traceid _stack_trace_id; 52 traceid _thread_id; 53 int _index; 54 size_t _span; 55 size_t _allocated; 56 unsigned int _stack_trace_hash; 57 bool _dead; 58 59 void set_dead() { 60 _dead = true; 61 } 62 63 void release_references() { 64 if (_thread_cp.valid()) { 65 _thread_cp.~JfrCheckpointBlobHandle(); 66 } 67 if (_klass_cp.valid()) { 68 _klass_cp.~JfrCheckpointBlobHandle(); 69 } 70 } 71 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: 80 ObjectSample() : _next(NULL), 81 _previous(NULL), 82 _thread_cp(), 83 _klass_cp(), 84 _object(NULL), 85 _allocation_time(0), 86 _stack_trace_id(0), 87 _thread_id(0), 88 _index(0), 89 _span(0), 90 _allocated(0), 91 _stack_trace_hash(0), 92 _dead(false) {} 93 94 ObjectSample* next() const { 95 return _next; 96 } 97 98 void set_next(ObjectSample* next) { 99 _next = next; 100 } 101 102 ObjectSample* prev() const { 103 return _previous; 104 } 105 106 void set_prev(ObjectSample* prev) { 107 _previous = prev; 108 } 109 110 bool is_dead() const { 111 return _dead; 112 } 113 114 const oop object() const { 115 return _object; 116 } 117 118 const oop* object_addr() const { 119 return &_object; 120 } 121 122 void set_object(oop object) { 123 _object = object; 124 } 125 126 const Klass* klass() const { 127 assert(_object != NULL, "invariant"); 128 return _object->klass(); 129 } 130 131 int index() const { 132 return _index; 133 } 134 135 void set_index(int index) { 136 _index = index; 137 } 138 139 size_t span() const { 140 return _span; 141 } 142 143 void set_span(size_t span) { 144 _span = span; 145 } 146 147 void add_span(size_t span) { 148 _span += span; 149 } 150 151 size_t allocated() const { 152 return _allocated; 153 } 154 155 void set_allocated(size_t size) { 156 _allocated = size; 157 } 158 159 const Ticks& allocation_time() const { 160 return _allocation_time; 161 } 162 163 const void set_allocation_time(const JfrTraceTime& time) { 164 _allocation_time = Ticks(time.value()); 165 } 166 167 bool has_stack_trace() const { 168 return stack_trace_id() != 0; 169 } 170 171 traceid stack_trace_id() const { 172 return _stack_trace_id; 173 } 174 175 void set_stack_trace_id(traceid id) { 176 _stack_trace_id = id; 177 } 178 179 unsigned int stack_trace_hash() const { 180 return _stack_trace_hash; 181 } 182 183 void set_stack_trace_hash(unsigned int hash) { 184 _stack_trace_hash = hash; 185 } 186 187 bool has_thread() const { 188 return _thread_id != 0; 189 } 190 191 traceid thread_id() const { 192 return _thread_id; 193 } 194 195 void set_thread_id(traceid id) { 196 _thread_id = id; 197 } 198 199 bool is_alive_and_older_than(jlong time_stamp) const { 200 return !is_dead() && (JfrTraceTime::is_ft_enabled() ? 201 _allocation_time.ft_value() : _allocation_time.value()) < time_stamp; 202 } 203 204 const JfrCheckpointBlobHandle& thread_checkpoint() const { 205 return _thread_cp; 206 } 207 208 bool has_thread_checkpoint() const { 209 return _thread_cp.valid(); 210 } 211 212 // JfrCheckpointBlobHandle assignment operator 213 // maintains proper reference counting 214 void set_thread_checkpoint(const JfrCheckpointBlobHandle& ref) { 215 if (_thread_cp != ref) { 216 _thread_cp = ref; 217 } 218 } 219 220 const JfrCheckpointBlobHandle& klass_checkpoint() const { 221 return _klass_cp; 222 } 223 224 bool has_klass_checkpoint() const { 225 return _klass_cp.valid(); 226 } 227 228 void set_klass_checkpoint(const JfrCheckpointBlobHandle& ref) { 229 if (_klass_cp != ref) { 230 if (_klass_cp.valid()) { 231 _klass_cp->set_next(ref); 232 return; 233 } 234 _klass_cp = ref; 235 } 236 } 237 }; 238 239 #endif // SHARE_VM_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP