|
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/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 * 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(), |
|
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 JfrTicks& 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() && (JfrTime::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 |