memTracker.hpp 20.4 KB
Newer Older
Z
zgu 已提交
1
/*
2
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
Z
zgu 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_VM_SERVICES_MEM_TRACKER_HPP
#define SHARE_VM_SERVICES_MEM_TRACKER_HPP

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#include "utilities/macros.hpp"

#if !INCLUDE_NMT

#include "utilities/ostream.hpp"

class BaselineOutputer : public StackObj {

};

class BaselineTTYOutputer : public BaselineOutputer {
  public:
    BaselineTTYOutputer(outputStream* st) { }
};

class MemTracker : AllStatic {
  public:
   enum ShutdownReason {
      NMT_shutdown_none,     // no shutdown requested
      NMT_shutdown_user,     // user requested shutdown
      NMT_normal,            // normal shutdown, process exit
      NMT_out_of_memory,     // shutdown due to out of memory
      NMT_initialization,    // shutdown due to initialization failure
      NMT_use_malloc_only,   // can not combine NMT with UseMallocOnly flag
      NMT_error_reporting,   // shutdown by vmError::report_and_die()
      NMT_out_of_generation, // running out of generation queue
      NMT_sequence_overflow  // overflow the sequence number
   };

57 58 59 60 61 62 63 64 65 66 67 68
  class Tracker {
   public:
    void discard() { }

    void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL) { }
    void record(address old_addr, address new_addr, size_t size,
      MEMFLAGS flags, address pc = NULL) { }
  };

  private:
   static Tracker  _tkr;

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

  public:
   static inline void init_tracking_options(const char* option_line) { }
   static inline bool is_on()   { return false; }
   static const char* reason()  { return "Native memory tracking is not implemented"; }
   static inline bool can_walk_stack() { return false; }

   static inline void bootstrap_single_thread() { }
   static inline void bootstrap_multi_thread() { }
   static inline void start() { }

   static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
        address pc = 0, Thread* thread = NULL) { }
   static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) { }
   static inline void record_arena_size(address addr, size_t size) { }
   static inline void record_virtual_memory_reserve(address addr, size_t size,
85 86 87
        MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { }
   static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size,
        MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { }
88 89 90 91
   static inline void record_virtual_memory_commit(address addr, size_t size,
        address pc = 0, Thread* thread = NULL) { }
   static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
        Thread* thread = NULL) { }
92 93 94
   static inline Tracker get_realloc_tracker() { return _tkr; }
   static inline Tracker get_virtual_memory_uncommit_tracker() { return _tkr; }
   static inline Tracker get_virtual_memory_release_tracker()  { return _tkr; }
95 96 97
   static inline bool baseline() { return false; }
   static inline bool has_baseline() { return false; }

98
   static inline void set_autoShutdown(bool value) { }
99
   static void shutdown(ShutdownReason reason) { }
100
   static inline bool shutdown_in_progress() { return false; }
101
   static bool print_memory_usage(BaselineOutputer& out, size_t unit,
102
            bool summary_only = true) { return false; }
103
   static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
104
            bool summary_only = true) { return false; }
105

106
   static bool wbtest_wait_for_data_merge() { return false; }
107

108 109 110 111 112 113 114
   static inline void sync() { }
   static inline void thread_exiting(JavaThread* thread) { }
};


#else // !INCLUDE_NMT

Z
zgu 已提交
115 116 117 118 119 120 121 122 123 124
#include "memory/allocation.hpp"
#include "runtime/globals.hpp"
#include "runtime/mutex.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
#include "services/memPtr.hpp"
#include "services/memRecorder.hpp"
#include "services/memSnapshot.hpp"
#include "services/memTrackWorker.hpp"

125 126
extern bool NMT_track_callsite;

127 128 129 130
#ifndef MAX_UNSIGNED_LONG
#define MAX_UNSIGNED_LONG    (unsigned long)(-1)
#endif

131 132
#ifdef ASSERT
  #define DEBUG_CALLER_PC  (NMT_track_callsite ? os::get_caller_pc(2) : 0)
Z
zgu 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
#else
  #define DEBUG_CALLER_PC  0
#endif

// The thread closure walks threads to collect per-thread
// memory recorders at NMT sync point
class SyncThreadRecorderClosure : public ThreadClosure {
 private:
  int _thread_count;

 public:
  SyncThreadRecorderClosure() {
    _thread_count =0;
  }

  void do_thread(Thread* thread);
  int  get_thread_count() const {
    return _thread_count;
  }
};

class BaselineOutputer;
class MemSnapshot;
class MemTrackWorker;
class Thread;
/*
 * MemTracker is the 'gate' class to native memory tracking runtime.
 */
class MemTracker : AllStatic {
162
  friend class GenerationData;
Z
zgu 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
  friend class MemTrackWorker;
  friend class MemSnapshot;
  friend class SyncThreadRecorderClosure;

  // NMT state
  enum NMTStates {
    NMT_uninited,                        // not yet initialized
    NMT_bootstrapping_single_thread,     // bootstrapping, VM is in single thread mode
    NMT_bootstrapping_multi_thread,      // bootstrapping, VM is about to enter multi-thread mode
    NMT_started,                         // NMT fully started
    NMT_shutdown_pending,                // shutdown pending
    NMT_final_shutdown,                  // in final phase of shutdown
    NMT_shutdown                         // shutdown
  };

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
 public:
  class Tracker : public StackObj {
    friend class MemTracker;
   public:
    enum MemoryOperation {
      NoOp,                   // no op
      Malloc,                 // malloc
      Realloc,                // realloc
      Free,                   // free
      Reserve,                // virtual memory reserve
      Commit,                 // virtual memory commit
      ReserveAndCommit,       // virtual memory reserve and commit
      StackAlloc = ReserveAndCommit, // allocate thread stack
      Type,                   // assign virtual memory type
      Uncommit,               // virtual memory uncommit
      Release,                // virtual memory release
      ArenaSize,              // set arena size
      StackRelease            // release thread stack
    };


   protected:
    Tracker(MemoryOperation op, Thread* thr = NULL);

   public:
    void discard();

    void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL);
    void record(address old_addr, address new_addr, size_t size,
      MEMFLAGS flags, address pc = NULL);

   private:
    bool            _need_thread_critical_lock;
    JavaThread*     _java_thread;
    MemoryOperation _op;          // memory operation
    jint            _seq;         // reserved sequence number
  };


217
 public:
Z
zgu 已提交
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
  // native memory tracking level
  enum NMTLevel {
    NMT_off,              // native memory tracking is off
    NMT_summary,          // don't track callsite
    NMT_detail            // track callsite also
  };

   enum ShutdownReason {
     NMT_shutdown_none,     // no shutdown requested
     NMT_shutdown_user,     // user requested shutdown
     NMT_normal,            // normal shutdown, process exit
     NMT_out_of_memory,     // shutdown due to out of memory
     NMT_initialization,    // shutdown due to initialization failure
     NMT_use_malloc_only,   // can not combine NMT with UseMallocOnly flag
     NMT_error_reporting,   // shutdown by vmError::report_and_die()
     NMT_out_of_generation, // running out of generation queue
     NMT_sequence_overflow  // overflow the sequence number
   };

 public:
  // initialize NMT tracking level from command line options, called
   // from VM command line parsing code
  static void init_tracking_options(const char* option_line);

  // if NMT is enabled to record memory activities
  static inline bool is_on() {
    return (_tracking_level >= NMT_summary &&
      _state >= NMT_bootstrapping_single_thread);
  }

248 249 250 251
  static inline enum NMTLevel tracking_level() {
    return _tracking_level;
  }

Z
zgu 已提交
252 253 254 255 256 257 258 259 260
  // user readable reason for shutting down NMT
  static const char* reason() {
    switch(_reason) {
      case NMT_shutdown_none:
        return "Native memory tracking is not enabled";
      case NMT_shutdown_user:
        return "Native memory tracking has been shutdown by user";
      case NMT_normal:
        return "Native memory tracking has been shutdown due to process exiting";
261 262
      case NMT_out_of_memory:
        return "Native memory tracking has been shutdown due to out of native memory";
Z
zgu 已提交
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
      case NMT_initialization:
        return "Native memory tracking failed to initialize";
      case NMT_error_reporting:
        return "Native memory tracking has been shutdown due to error reporting";
      case NMT_out_of_generation:
        return "Native memory tracking has been shutdown due to running out of generation buffer";
      case NMT_sequence_overflow:
        return "Native memory tracking has been shutdown due to overflow the sequence number";
      case NMT_use_malloc_only:
        return "Native memory tracking is not supported when UseMallocOnly is on";
      default:
        ShouldNotReachHere();
        return NULL;
    }
  }

  // test if we can walk native stack
  static bool can_walk_stack() {
  // native stack is not walkable during bootstrapping on sparc
#if defined(SPARC)
    return (_state == NMT_started);
#else
    return (_state >= NMT_bootstrapping_single_thread && _state  <= NMT_started);
#endif
  }

  // if native memory tracking tracks callsite
  static inline bool track_callsite() { return _tracking_level == NMT_detail; }

292 293 294 295 296 297 298 299 300 301
  // NMT automatically shuts itself down under extreme situation by default.
  // When the value is set to false,  NMT will try its best to stay alive,
  // even it has to slow down VM.
  static inline void set_autoShutdown(bool value) {
    AutoShutdownNMT = value;
    if (AutoShutdownNMT && _slowdown_calling_thread) {
      _slowdown_calling_thread = false;
    }
  }

Z
zgu 已提交
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
  // shutdown native memory tracking capability. Native memory tracking
  // can be shutdown by VM when it encounters low memory scenarios.
  // Memory tracker should gracefully shutdown itself, and preserve the
  // latest memory statistics for post morten diagnosis.
  static void shutdown(ShutdownReason reason);

  // if there is shutdown requested
  static inline bool shutdown_in_progress() {
    return (_state >= NMT_shutdown_pending);
  }

  // bootstrap native memory tracking, so it can start to collect raw data
  // before worker thread can start

  // the first phase of bootstrapping, when VM still in single-threaded mode
  static void bootstrap_single_thread();
  // the second phase of bootstrapping, VM is about or already in multi-threaded mode
  static void bootstrap_multi_thread();


  // start() has to be called when VM still in single thread mode, but after
  // command line option parsing is done.
  static void start();

  // record a 'malloc' call
  static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
                            address pc = 0, Thread* thread = NULL) {
329 330
    Tracker tkr(Tracker::Malloc, thread);
    tkr.record(addr, size, flags, pc);
Z
zgu 已提交
331 332 333
  }
  // record a 'free' call
  static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) {
334 335
    Tracker tkr(Tracker::Free, thread);
    tkr.record(addr, 0, flags, DEBUG_CALLER_PC);
Z
zgu 已提交
336 337 338
  }

  static inline void record_arena_size(address addr, size_t size) {
339 340
    Tracker tkr(Tracker::ArenaSize);
    tkr.record(addr, size);
Z
zgu 已提交
341 342 343 344
  }

  // record a virtual memory 'reserve' call
  static inline void record_virtual_memory_reserve(address addr, size_t size,
345 346 347 348
                     MEMFLAGS flags, address pc = 0, Thread* thread = NULL) {
    assert(size > 0, "Sanity check");
    Tracker tkr(Tracker::Reserve, thread);
    tkr.record(addr, size, flags, pc);
Z
zgu 已提交
349 350
  }

351 352
  static inline void record_thread_stack(address addr, size_t size, Thread* thr,
                           address pc = 0) {
353 354
    Tracker tkr(Tracker::StackAlloc, thr);
    tkr.record(addr, size, mtThreadStack, pc);
355 356 357
  }

  static inline void release_thread_stack(address addr, size_t size, Thread* thr) {
358 359
    Tracker tkr(Tracker::StackRelease, thr);
    tkr.record(addr, size, mtThreadStack, DEBUG_CALLER_PC);
360 361
  }

Z
zgu 已提交
362 363
  // record a virtual memory 'commit' call
  static inline void record_virtual_memory_commit(address addr, size_t size,
364
                            address pc, Thread* thread = NULL) {
365 366
    Tracker tkr(Tracker::Commit, thread);
    tkr.record(addr, size, mtNone, pc);
Z
zgu 已提交
367 368
  }

369 370 371 372
  static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size,
    MEMFLAGS flags, address pc, Thread* thread = NULL) {
    Tracker tkr(Tracker::ReserveAndCommit, thread);
    tkr.record(addr, size, flags, pc);
Z
zgu 已提交
373 374 375 376 377 378
  }


  // record memory type on virtual memory base address
  static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
                            Thread* thread = NULL) {
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
    Tracker tkr(Tracker::Type);
    tkr.record(base, 0, flags);
  }

  // Get memory trackers for memory operations that can result race conditions.
  // The memory tracker has to be obtained before realloc, virtual memory uncommit
  // and virtual memory release, and call tracker.record() method if operation
  // succeeded, or tracker.discard() to abort the tracking.
  static inline Tracker get_realloc_tracker() {
    return Tracker(Tracker::Realloc);
  }

  static inline Tracker get_virtual_memory_uncommit_tracker() {
    return Tracker(Tracker::Uncommit);
  }

  static inline Tracker get_virtual_memory_release_tracker() {
    return Tracker(Tracker::Release);
Z
zgu 已提交
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
  }


  // create memory baseline of current memory snapshot
  static bool baseline();
  // is there a memory baseline
  static bool has_baseline() {
    return _baseline.baselined();
  }

  // print memory usage from current snapshot
  static bool print_memory_usage(BaselineOutputer& out, size_t unit,
           bool summary_only = true);
  // compare memory usage between current snapshot and baseline
  static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
           bool summary_only = true);

414 415 416 417 418
  // the version for whitebox testing support, it ensures that all memory
  // activities before this method call, are reflected in the snapshot
  // database.
  static bool wbtest_wait_for_data_merge();

Z
zgu 已提交
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
  // sync is called within global safepoint to synchronize nmt data
  static void sync();

  // called when a thread is about to exit
  static void thread_exiting(JavaThread* thread);

  // retrieve global snapshot
  static MemSnapshot* get_snapshot() {
    if (shutdown_in_progress()) {
      return NULL;
    }
    return _snapshot;
  }

  // print tracker stats
  NOT_PRODUCT(static void print_tracker_stats(outputStream* st);)
  NOT_PRODUCT(static void walk_stack(int toSkip, char* buf, int len);)

 private:
  // start native memory tracking worker thread
439
  static bool start_worker(MemSnapshot* snapshot);
Z
zgu 已提交
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461

  // called by worker thread to complete shutdown process
  static void final_shutdown();

 protected:
  // retrieve per-thread recorder of the specified thread.
  // if the recorder is full, it will be enqueued to overflow
  // queue, a new recorder is acquired from recorder pool or a
  // new instance is created.
  // when thread == NULL, it means global recorder
  static MemRecorder* get_thread_recorder(JavaThread* thread);

  // per-thread recorder pool
  static void release_thread_recorder(MemRecorder* rec);
  static void delete_all_pooled_recorders();

  // pending recorder queue. Recorders are queued to pending queue
  // when they are overflowed or collected at nmt sync point.
  static void enqueue_pending_recorder(MemRecorder* rec);
  static MemRecorder* get_pending_recorders();
  static void delete_all_pending_recorders();

462 463 464 465 466 467 468 469 470 471 472
  // write a memory tracking record in recorder
  static void write_tracking_record(address addr, MEMFLAGS type,
    size_t size, jint seq, address pc, JavaThread* thread);

  static bool is_single_threaded_bootstrap() {
    return _state == NMT_bootstrapping_single_thread;
  }

  static void check_NMT_load(Thread* thr) {
    assert(thr != NULL, "Sanity check");
    if (_slowdown_calling_thread && thr != _worker_thread) {
473 474 475
#ifdef _WINDOWS
      // On Windows, os::NakedYield() does not work as well
      // as os::yield_all()
476
      os::yield_all();
477 478 479 480 481 482 483 484 485 486 487
#else
     // On Solaris, os::yield_all() depends on os::sleep()
     // which requires JavaTherad in _thread_in_vm state.
     // Transits thread to _thread_in_vm state can be dangerous
     // if caller holds lock, as it may deadlock with Threads_lock.
     // So use NaKedYield instead.
     //
     // Linux and BSD, NakedYield() and yield_all() implementations
     // are the same.
      os::NakedYield();
#endif
488 489 490 491 492 493 494 495 496 497 498 499 500
    }
  }

  static void inc_pending_op_count() {
    Atomic::inc(&_pending_op_count);
  }

  static void dec_pending_op_count() {
    Atomic::dec(&_pending_op_count);
    assert(_pending_op_count >= 0, "Sanity check");
  }


Z
zgu 已提交
501 502 503 504 505 506 507
 private:
  // retrieve a pooled memory record or create new one if there is not
  // one available
  static MemRecorder* get_new_or_pooled_instance();
  static void create_memory_record(address addr, MEMFLAGS type,
                   size_t size, address pc, Thread* thread);
  static void create_record_in_recorder(address addr, MEMFLAGS type,
508
                   size_t size, address pc, JavaThread* thread);
Z
zgu 已提交
509

510 511 512 513 514 515 516 517 518
  static void set_current_processing_generation(unsigned long generation) {
    _worker_thread_idle = false;
    _processing_generation = generation;
  }

  static void report_worker_idle() {
    _worker_thread_idle = true;
  }

Z
zgu 已提交
519 520 521 522 523 524 525 526
 private:
  // global memory snapshot
  static MemSnapshot*     _snapshot;

  // a memory baseline of snapshot
  static MemBaseline      _baseline;

  // query lock
527
  static Mutex*           _query_lock;
Z
zgu 已提交
528 529 530 531

  // a thread can start to allocate memory before it is attached
  // to VM 'Thread', those memory activities are recorded here.
  // ThreadCritical is required to guard this global recorder.
532
  static MemRecorder* volatile _global_recorder;
Z
zgu 已提交
533 534 535 536 537

  // main thread id
  debug_only(static intx   _main_thread_tid;)

  // pending recorders to be merged
538
  static MemRecorder* volatile     _merge_pending_queue;
Z
zgu 已提交
539 540 541 542

  NOT_PRODUCT(static volatile jint   _pending_recorder_count;)

  // pooled memory recorders
543
  static MemRecorder* volatile     _pooled_recorders;
Z
zgu 已提交
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569

  // memory recorder pool management, uses following
  // counter to determine if a released memory recorder
  // should be pooled

  // latest thread count
  static int               _thread_count;
  // pooled recorder count
  static volatile jint     _pooled_recorder_count;


  // worker thread to merge pending recorders into snapshot
  static MemTrackWorker*  _worker_thread;

  // how many safepoints we skipped without entering sync point
  static int              _sync_point_skip_count;

  // if the tracker is properly intialized
  static bool             _is_tracker_ready;
  // tracking level (off, summary and detail)
  static enum NMTLevel    _tracking_level;

  // current nmt state
  static volatile enum NMTStates   _state;
  // the reason for shutting down nmt
  static enum ShutdownReason       _reason;
570 571 572 573 574
  // the generation that NMT is processing
  static volatile unsigned long    _processing_generation;
  // although NMT is still procesing current generation, but
  // there is not more recorder to process, set idle state
  static volatile bool             _worker_thread_idle;
575 576 577 578

  // if NMT should slow down calling thread to allow
  // worker thread to catch up
  static volatile bool             _slowdown_calling_thread;
579 580 581 582 583 584

  // pending memory op count.
  // Certain memory ops need to pre-reserve sequence number
  // before memory operation can happen to avoid race condition.
  // See MemTracker::Tracker for detail
  static volatile jint             _pending_op_count;
Z
zgu 已提交
585 586
};

587 588
#endif // !INCLUDE_NMT

Z
zgu 已提交
589
#endif // SHARE_VM_SERVICES_MEM_TRACKER_HPP