hotspot/src/share/vm/services/classLoadingService.cpp
author ysr
Wed, 23 Dec 2009 09:23:54 -0800
changeset 4574 b2d5b0975515
parent 1 489c9b5090e2
child 4576 ad45d4e37837
permissions -rw-r--r--
6631166: CMS: better heuristics when combatting fragmentation Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking. Reviewed-by: jmasa
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
     2
 * Copyright 2003-2005 Sun Microsystems, Inc.  All Rights Reserved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
# include "incls/_precompiled.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
# include "incls/_classLoadingService.cpp.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
#ifdef DTRACE_ENABLED
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
// Only bother with this argument setup if dtrace is available
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
HS_DTRACE_PROBE_DECL4(hotspot, class__loaded, char*, int, oop, bool);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
HS_DTRACE_PROBE_DECL4(hotspot, class__unloaded, char*, int, oop, bool);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
#define DTRACE_CLASSLOAD_PROBE(type, clss, shared)  \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
  {                                                 \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
    char* data = NULL;                              \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
    int len = 0;                                    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
    symbolOop name = (clss)->name();                \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
    if (name != NULL) {                             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
      data = (char*)name->bytes();                  \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
      len = name->utf8_length();                    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
    }                                               \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
    HS_DTRACE_PROBE4(hotspot, class__##type,        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
      data, len, (clss)->class_loader(), (shared)); \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
#else //  ndef DTRACE_ENABLED
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
#define DTRACE_CLASSLOAD_PROBE(type, clss, shared)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
// counters for classes loaded from class files
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
PerfCounter*    ClassLoadingService::_classes_loaded_count = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
PerfCounter*    ClassLoadingService::_classes_unloaded_count = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
PerfCounter*    ClassLoadingService::_classbytes_loaded = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
PerfCounter*    ClassLoadingService::_classbytes_unloaded = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
// counters for classes loaded from shared archive
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
PerfCounter*    ClassLoadingService::_shared_classes_loaded_count = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
PerfCounter*    ClassLoadingService::_shared_classes_unloaded_count = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
PerfCounter*    ClassLoadingService::_shared_classbytes_loaded = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
PerfCounter*    ClassLoadingService::_shared_classbytes_unloaded = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
PerfVariable*   ClassLoadingService::_class_methods_size = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
void ClassLoadingService::init() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  EXCEPTION_MARK;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
  // These counters are for java.lang.management API support.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
  // They are created even if -XX:-UsePerfData is set and in
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
  // that case, they will be allocated on C heap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
  _classes_loaded_count =
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
                 PerfDataManager::create_counter(JAVA_CLS, "loadedClasses",
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
                                                 PerfData::U_Events, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
  _classes_unloaded_count =
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
                 PerfDataManager::create_counter(JAVA_CLS, "unloadedClasses",
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
                                                 PerfData::U_Events, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
  _shared_classes_loaded_count =
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
                 PerfDataManager::create_counter(JAVA_CLS, "sharedLoadedClasses",
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
                                                 PerfData::U_Events, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
  _shared_classes_unloaded_count =
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
                 PerfDataManager::create_counter(JAVA_CLS, "sharedUnloadedClasses",
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
                                                 PerfData::U_Events, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
    _classbytes_loaded =
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
                 PerfDataManager::create_counter(SUN_CLS, "loadedBytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
                                                 PerfData::U_Bytes, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
    _classbytes_unloaded =
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
                 PerfDataManager::create_counter(SUN_CLS, "unloadedBytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
                                                 PerfData::U_Bytes, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
    _shared_classbytes_loaded =
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
                 PerfDataManager::create_counter(SUN_CLS, "sharedLoadedBytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
                                                 PerfData::U_Bytes, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
    _shared_classbytes_unloaded =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
                 PerfDataManager::create_counter(SUN_CLS, "sharedUnloadedBytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
                                                 PerfData::U_Bytes, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
    _class_methods_size =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
                 PerfDataManager::create_variable(SUN_CLS, "methodBytes",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
                                                  PerfData::U_Bytes, CHECK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
void ClassLoadingService::notify_class_unloaded(instanceKlass* k) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
  DTRACE_CLASSLOAD_PROBE(unloaded, k, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
  // Classes that can be unloaded must be non-shared
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
  _classes_unloaded_count->inc();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
    // add the class size
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
    size_t size = compute_class_size(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
    _classbytes_unloaded->inc(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
    // Compute method size & subtract from running total.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
    // We are called during phase 1 of mark sweep, so it's
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
    // still ok to iterate through methodOops here.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
    objArrayOop methods = k->methods();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
    for (int i = 0; i < methods->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
      _class_methods_size->inc(-methods->obj_at(i)->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
  if (TraceClassUnloading) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
    ResourceMark rm;
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 1
diff changeset
   131
    gclog_or_tty->print_cr("[Unloading class %s]", k->external_name());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
void ClassLoadingService::notify_class_loaded(instanceKlass* k, bool shared_class) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
  DTRACE_CLASSLOAD_PROBE(loaded, k, shared_class);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
  PerfCounter* classes_counter = (shared_class ? _shared_classes_loaded_count
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
                                               : _classes_loaded_count);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
  // increment the count
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
  classes_counter->inc();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  if (UsePerfData) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
    PerfCounter* classbytes_counter = (shared_class ? _shared_classbytes_loaded
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
                                                    : _classbytes_loaded);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
    // add the class size
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
    size_t size = compute_class_size(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
    classbytes_counter->inc(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
size_t ClassLoadingService::compute_class_size(instanceKlass* k) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
  // lifted from ClassStatistics.do_class(klassOop k)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
  size_t class_size = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
  class_size += k->as_klassOop()->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
  if (k->oop_is_instance()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
    class_size += k->methods()->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
    class_size += k->constants()->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
    class_size += k->local_interfaces()->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
    class_size += k->transitive_interfaces()->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
    // We do not have to count implementors, since we only store one!
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
    class_size += k->fields()->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
  return class_size * oopSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
bool ClassLoadingService::set_verbose(bool verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
  MutexLocker m(Management_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
  // verbose will be set to the previous value
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
  bool succeed = CommandLineFlags::boolAtPut((char*)"TraceClassLoading", &verbose, MANAGEMENT);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
  assert(succeed, "Setting TraceClassLoading flag fails");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
  reset_trace_class_unloading();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  return verbose;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
// Caller to this function must own Management_lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
void ClassLoadingService::reset_trace_class_unloading() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
  assert(Management_lock->owned_by_self(), "Must own the Management_lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
  bool value = MemoryService::get_verbose() || ClassLoadingService::get_verbose();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
  bool succeed = CommandLineFlags::boolAtPut((char*)"TraceClassUnloading", &value, MANAGEMENT);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  assert(succeed, "Setting TraceClassUnLoading flag fails");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
GrowableArray<KlassHandle>* LoadedClassesEnumerator::_loaded_classes = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
Thread* LoadedClassesEnumerator::_current_thread = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
LoadedClassesEnumerator::LoadedClassesEnumerator(Thread* cur_thread) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
  assert(cur_thread == Thread::current(), "Check current thread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
  int init_size = ClassLoadingService::loaded_class_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
  _klass_handle_array = new GrowableArray<KlassHandle>(init_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
  // For consistency of the loaded classes, grab the SystemDictionary lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  MutexLocker sd_mutex(SystemDictionary_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
  // Set _loaded_classes and _current_thread and begin enumerating all classes.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
  // Only one thread will do the enumeration at a time.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
  // These static variables are needed and they are used by the static method
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
  // add_loaded_class called from classes_do().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
  _loaded_classes = _klass_handle_array;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
  _current_thread = cur_thread;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
  SystemDictionary::classes_do(&add_loaded_class);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
  // FIXME: Exclude array klasses for now
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
  // Universe::basic_type_classes_do(&add_loaded_class);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
}