memTracker.hpp revision 3730:fb19af007ffc
1/*
2 * Copyright (c) 2012, 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_SERVICES_MEM_TRACKER_HPP
26#define SHARE_VM_SERVICES_MEM_TRACKER_HPP
27
28#include "utilities/macros.hpp"
29
30#if !INCLUDE_NMT
31
32#include "utilities/ostream.hpp"
33
34class BaselineOutputer : public StackObj {
35
36};
37
38class BaselineTTYOutputer : public BaselineOutputer {
39  public:
40    BaselineTTYOutputer(outputStream* st) { }
41};
42
43class MemTracker : AllStatic {
44  public:
45   enum ShutdownReason {
46      NMT_shutdown_none,     // no shutdown requested
47      NMT_shutdown_user,     // user requested shutdown
48      NMT_normal,            // normal shutdown, process exit
49      NMT_out_of_memory,     // shutdown due to out of memory
50      NMT_initialization,    // shutdown due to initialization failure
51      NMT_use_malloc_only,   // can not combine NMT with UseMallocOnly flag
52      NMT_error_reporting,   // shutdown by vmError::report_and_die()
53      NMT_out_of_generation, // running out of generation queue
54      NMT_sequence_overflow  // overflow the sequence number
55   };
56
57
58  public:
59   static inline void init_tracking_options(const char* option_line) { }
60   static inline bool is_on()   { return false; }
61   static const char* reason()  { return "Native memory tracking is not implemented"; }
62   static inline bool can_walk_stack() { return false; }
63
64   static inline void bootstrap_single_thread() { }
65   static inline void bootstrap_multi_thread() { }
66   static inline void start() { }
67
68   static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
69        address pc = 0, Thread* thread = NULL) { }
70   static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) { }
71   static inline void record_realloc(address old_addr, address new_addr, size_t size,
72        MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { }
73   static inline void record_arena_size(address addr, size_t size) { }
74   static inline void record_virtual_memory_reserve(address addr, size_t size,
75        address pc = 0, Thread* thread = NULL) { }
76   static inline void record_virtual_memory_commit(address addr, size_t size,
77        address pc = 0, Thread* thread = NULL) { }
78   static inline void record_virtual_memory_uncommit(address addr, size_t size,
79        Thread* thread = NULL) { }
80   static inline void record_virtual_memory_release(address addr, size_t size,
81        Thread* thread = NULL) { }
82   static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
83        Thread* thread = NULL) { }
84   static inline bool baseline() { return false; }
85   static inline bool has_baseline() { return false; }
86
87   static void shutdown(ShutdownReason reason) { }
88   static inline bool shutdown_in_progress() {  }
89   static bool print_memory_usage(BaselineOutputer& out, size_t unit,
90            bool summary_only = true) { }
91   static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
92            bool summary_only = true) { }
93
94   static inline void sync() { }
95   static inline void thread_exiting(JavaThread* thread) { }
96
97};
98
99
100#else // !INCLUDE_NMT
101
102#include "memory/allocation.hpp"
103#include "runtime/globals.hpp"
104#include "runtime/mutex.hpp"
105#include "runtime/os.hpp"
106#include "runtime/thread.hpp"
107#include "services/memPtr.hpp"
108#include "services/memRecorder.hpp"
109#include "services/memSnapshot.hpp"
110#include "services/memTrackWorker.hpp"
111
112#ifdef SOLARIS
113#include "thread_solaris.inline.hpp"
114#endif
115
116#ifdef _DEBUG
117  #define DEBUG_CALLER_PC  os::get_caller_pc(3)
118#else
119  #define DEBUG_CALLER_PC  0
120#endif
121
122// The thread closure walks threads to collect per-thread
123// memory recorders at NMT sync point
124class SyncThreadRecorderClosure : public ThreadClosure {
125 private:
126  int _thread_count;
127
128 public:
129  SyncThreadRecorderClosure() {
130    _thread_count =0;
131  }
132
133  void do_thread(Thread* thread);
134  int  get_thread_count() const {
135    return _thread_count;
136  }
137};
138
139class BaselineOutputer;
140class MemSnapshot;
141class MemTrackWorker;
142class Thread;
143/*
144 * MemTracker is the 'gate' class to native memory tracking runtime.
145 */
146class MemTracker : AllStatic {
147  friend class MemTrackWorker;
148  friend class MemSnapshot;
149  friend class SyncThreadRecorderClosure;
150
151  // NMT state
152  enum NMTStates {
153    NMT_uninited,                        // not yet initialized
154    NMT_bootstrapping_single_thread,     // bootstrapping, VM is in single thread mode
155    NMT_bootstrapping_multi_thread,      // bootstrapping, VM is about to enter multi-thread mode
156    NMT_started,                         // NMT fully started
157    NMT_shutdown_pending,                // shutdown pending
158    NMT_final_shutdown,                  // in final phase of shutdown
159    NMT_shutdown                         // shutdown
160  };
161
162 public:
163  // native memory tracking level
164  enum NMTLevel {
165    NMT_off,              // native memory tracking is off
166    NMT_summary,          // don't track callsite
167    NMT_detail            // track callsite also
168  };
169
170   enum ShutdownReason {
171     NMT_shutdown_none,     // no shutdown requested
172     NMT_shutdown_user,     // user requested shutdown
173     NMT_normal,            // normal shutdown, process exit
174     NMT_out_of_memory,     // shutdown due to out of memory
175     NMT_initialization,    // shutdown due to initialization failure
176     NMT_use_malloc_only,   // can not combine NMT with UseMallocOnly flag
177     NMT_error_reporting,   // shutdown by vmError::report_and_die()
178     NMT_out_of_generation, // running out of generation queue
179     NMT_sequence_overflow  // overflow the sequence number
180   };
181
182 public:
183  // initialize NMT tracking level from command line options, called
184   // from VM command line parsing code
185  static void init_tracking_options(const char* option_line);
186
187  // if NMT is enabled to record memory activities
188  static inline bool is_on() {
189    return (_tracking_level >= NMT_summary &&
190      _state >= NMT_bootstrapping_single_thread);
191  }
192
193  static inline enum NMTLevel tracking_level() {
194    return _tracking_level;
195  }
196
197  // user readable reason for shutting down NMT
198  static const char* reason() {
199    switch(_reason) {
200      case NMT_shutdown_none:
201        return "Native memory tracking is not enabled";
202      case NMT_shutdown_user:
203        return "Native memory tracking has been shutdown by user";
204      case NMT_normal:
205        return "Native memory tracking has been shutdown due to process exiting";
206      case NMT_out_of_memory:
207        return "Native memory tracking has been shutdown due to out of native memory";
208      case NMT_initialization:
209        return "Native memory tracking failed to initialize";
210      case NMT_error_reporting:
211        return "Native memory tracking has been shutdown due to error reporting";
212      case NMT_out_of_generation:
213        return "Native memory tracking has been shutdown due to running out of generation buffer";
214      case NMT_sequence_overflow:
215        return "Native memory tracking has been shutdown due to overflow the sequence number";
216      case NMT_use_malloc_only:
217        return "Native memory tracking is not supported when UseMallocOnly is on";
218      default:
219        ShouldNotReachHere();
220        return NULL;
221    }
222  }
223
224  // test if we can walk native stack
225  static bool can_walk_stack() {
226  // native stack is not walkable during bootstrapping on sparc
227#if defined(SPARC)
228    return (_state == NMT_started);
229#else
230    return (_state >= NMT_bootstrapping_single_thread && _state  <= NMT_started);
231#endif
232  }
233
234  // if native memory tracking tracks callsite
235  static inline bool track_callsite() { return _tracking_level == NMT_detail; }
236
237  // shutdown native memory tracking capability. Native memory tracking
238  // can be shutdown by VM when it encounters low memory scenarios.
239  // Memory tracker should gracefully shutdown itself, and preserve the
240  // latest memory statistics for post morten diagnosis.
241  static void shutdown(ShutdownReason reason);
242
243  // if there is shutdown requested
244  static inline bool shutdown_in_progress() {
245    return (_state >= NMT_shutdown_pending);
246  }
247
248  // bootstrap native memory tracking, so it can start to collect raw data
249  // before worker thread can start
250
251  // the first phase of bootstrapping, when VM still in single-threaded mode
252  static void bootstrap_single_thread();
253  // the second phase of bootstrapping, VM is about or already in multi-threaded mode
254  static void bootstrap_multi_thread();
255
256
257  // start() has to be called when VM still in single thread mode, but after
258  // command line option parsing is done.
259  static void start();
260
261  // record a 'malloc' call
262  static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
263                            address pc = 0, Thread* thread = NULL) {
264    if (NMT_CAN_TRACK(flags)) {
265      assert(size > 0, "Sanity check");
266      create_memory_record(addr, (flags|MemPointerRecord::malloc_tag()), size, pc, thread);
267    }
268  }
269  // record a 'free' call
270  static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) {
271    if (is_on() && NMT_CAN_TRACK(flags)) {
272      create_memory_record(addr, MemPointerRecord::free_tag(), 0, 0, thread);
273    }
274  }
275  // record a 'realloc' call
276  static inline void record_realloc(address old_addr, address new_addr, size_t size,
277       MEMFLAGS flags, address pc = 0, Thread* thread = NULL) {
278    if (is_on()) {
279      assert(size > 0, "Sanity check");
280      record_free(old_addr, flags, thread);
281      record_malloc(new_addr, size, flags, pc, thread);
282    }
283  }
284
285  // record arena size
286  static inline void record_arena_size(address addr, size_t size) {
287    // we add a positive offset to arena address, so we can have arena size record
288    // sorted after arena record
289    if (is_on() && !UseMallocOnly) {
290      assert(addr != NULL, "Sanity check");
291      create_memory_record((addr + sizeof(void*)), MemPointerRecord::arena_size_tag(), size,
292        0, NULL);
293    }
294  }
295
296  // record a virtual memory 'reserve' call
297  static inline void record_virtual_memory_reserve(address addr, size_t size,
298                            address pc = 0, Thread* thread = NULL) {
299    if (is_on()) {
300      assert(size > 0, "Sanity check");
301      create_memory_record(addr, MemPointerRecord::virtual_memory_reserve_tag(),
302                           size, pc, thread);
303    }
304  }
305
306  static inline void record_thread_stack(address addr, size_t size, Thread* thr,
307                           address pc = 0) {
308    if (is_on()) {
309      assert(size > 0 && thr != NULL, "Sanity check");
310      create_memory_record(addr, MemPointerRecord::virtual_memory_reserve_tag() | mtThreadStack,
311                          size, pc, thr);
312      create_memory_record(addr, MemPointerRecord::virtual_memory_commit_tag() | mtThreadStack,
313                          size, pc, thr);
314    }
315  }
316
317  static inline void release_thread_stack(address addr, size_t size, Thread* thr) {
318    if (is_on()) {
319      assert(size > 0 && thr != NULL, "Sanity check");
320      create_memory_record(addr, MemPointerRecord::virtual_memory_uncommit_tag() | mtThreadStack,
321                          size, DEBUG_CALLER_PC, thr);
322      create_memory_record(addr, MemPointerRecord::virtual_memory_release_tag() | mtThreadStack,
323                          size, DEBUG_CALLER_PC, thr);
324    }
325  }
326
327  // record a virtual memory 'commit' call
328  static inline void record_virtual_memory_commit(address addr, size_t size,
329                            address pc = 0, Thread* thread = NULL) {
330    if (is_on()) {
331      assert(size > 0, "Sanity check");
332      create_memory_record(addr, MemPointerRecord::virtual_memory_commit_tag(),
333                           size, DEBUG_CALLER_PC, thread);
334    }
335  }
336
337  // record a virtual memory 'uncommit' call
338  static inline void record_virtual_memory_uncommit(address addr, size_t size,
339                            Thread* thread = NULL) {
340    if (is_on()) {
341      assert(size > 0, "Sanity check");
342      create_memory_record(addr, MemPointerRecord::virtual_memory_uncommit_tag(),
343                           size, DEBUG_CALLER_PC, thread);
344    }
345  }
346
347  // record a virtual memory 'release' call
348  static inline void record_virtual_memory_release(address addr, size_t size,
349                            Thread* thread = NULL) {
350    if (is_on()) {
351      assert(size > 0, "Sanity check");
352      create_memory_record(addr, MemPointerRecord::virtual_memory_release_tag(),
353                           size, DEBUG_CALLER_PC, thread);
354    }
355  }
356
357  // record memory type on virtual memory base address
358  static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
359                            Thread* thread = NULL) {
360    if (is_on()) {
361      assert(base > 0, "wrong base address");
362      assert((flags & (~mt_masks)) == 0, "memory type only");
363      create_memory_record(base, (flags | MemPointerRecord::virtual_memory_type_tag()),
364                           0, DEBUG_CALLER_PC, thread);
365    }
366  }
367
368
369  // create memory baseline of current memory snapshot
370  static bool baseline();
371  // is there a memory baseline
372  static bool has_baseline() {
373    return _baseline.baselined();
374  }
375
376  // print memory usage from current snapshot
377  static bool print_memory_usage(BaselineOutputer& out, size_t unit,
378           bool summary_only = true);
379  // compare memory usage between current snapshot and baseline
380  static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
381           bool summary_only = true);
382
383  // sync is called within global safepoint to synchronize nmt data
384  static void sync();
385
386  // called when a thread is about to exit
387  static void thread_exiting(JavaThread* thread);
388
389  // retrieve global snapshot
390  static MemSnapshot* get_snapshot() {
391    if (shutdown_in_progress()) {
392      return NULL;
393    }
394    return _snapshot;
395  }
396
397  // print tracker stats
398  NOT_PRODUCT(static void print_tracker_stats(outputStream* st);)
399  NOT_PRODUCT(static void walk_stack(int toSkip, char* buf, int len);)
400
401 private:
402  // start native memory tracking worker thread
403  static bool start_worker();
404
405  // called by worker thread to complete shutdown process
406  static void final_shutdown();
407
408 protected:
409  // retrieve per-thread recorder of the specified thread.
410  // if the recorder is full, it will be enqueued to overflow
411  // queue, a new recorder is acquired from recorder pool or a
412  // new instance is created.
413  // when thread == NULL, it means global recorder
414  static MemRecorder* get_thread_recorder(JavaThread* thread);
415
416  // per-thread recorder pool
417  static void release_thread_recorder(MemRecorder* rec);
418  static void delete_all_pooled_recorders();
419
420  // pending recorder queue. Recorders are queued to pending queue
421  // when they are overflowed or collected at nmt sync point.
422  static void enqueue_pending_recorder(MemRecorder* rec);
423  static MemRecorder* get_pending_recorders();
424  static void delete_all_pending_recorders();
425
426 private:
427  // retrieve a pooled memory record or create new one if there is not
428  // one available
429  static MemRecorder* get_new_or_pooled_instance();
430  static void create_memory_record(address addr, MEMFLAGS type,
431                   size_t size, address pc, Thread* thread);
432  static void create_record_in_recorder(address addr, MEMFLAGS type,
433                   size_t size, address pc, JavaThread* thread);
434
435 private:
436  // global memory snapshot
437  static MemSnapshot*     _snapshot;
438
439  // a memory baseline of snapshot
440  static MemBaseline      _baseline;
441
442  // query lock
443  static Mutex*           _query_lock;
444
445  // a thread can start to allocate memory before it is attached
446  // to VM 'Thread', those memory activities are recorded here.
447  // ThreadCritical is required to guard this global recorder.
448  static MemRecorder*     _global_recorder;
449
450  // main thread id
451  debug_only(static intx   _main_thread_tid;)
452
453  // pending recorders to be merged
454  static volatile MemRecorder*      _merge_pending_queue;
455
456  NOT_PRODUCT(static volatile jint   _pending_recorder_count;)
457
458  // pooled memory recorders
459  static volatile MemRecorder*      _pooled_recorders;
460
461  // memory recorder pool management, uses following
462  // counter to determine if a released memory recorder
463  // should be pooled
464
465  // latest thread count
466  static int               _thread_count;
467  // pooled recorder count
468  static volatile jint     _pooled_recorder_count;
469
470
471  // worker thread to merge pending recorders into snapshot
472  static MemTrackWorker*  _worker_thread;
473
474  // how many safepoints we skipped without entering sync point
475  static int              _sync_point_skip_count;
476
477  // if the tracker is properly intialized
478  static bool             _is_tracker_ready;
479  // tracking level (off, summary and detail)
480  static enum NMTLevel    _tracking_level;
481
482  // current nmt state
483  static volatile enum NMTStates   _state;
484  // the reason for shutting down nmt
485  static enum ShutdownReason       _reason;
486};
487
488#endif // !INCLUDE_NMT
489
490#endif // SHARE_VM_SERVICES_MEM_TRACKER_HPP
491