src/share/vm/runtime/statSampler.cpp

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 2708
1d1603768966
parent 1
2d8a650513c2
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 2001, 2011, 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  */
    25 /*
    26  * This file has been modified by Loongson Technology in 2015. These
    27  * modifications are Copyright (c) 2015 Loongson Technology, and are made
    28  * available on the same license terms set forth above.
    29  */
    31 #include "precompiled.hpp"
    32 #include "classfile/systemDictionary.hpp"
    33 #include "classfile/vmSymbols.hpp"
    34 #include "memory/allocation.inline.hpp"
    35 #include "memory/resourceArea.hpp"
    36 #include "oops/oop.inline.hpp"
    37 #include "runtime/arguments.hpp"
    38 #include "runtime/java.hpp"
    39 #include "runtime/javaCalls.hpp"
    40 #include "runtime/os.hpp"
    41 #include "runtime/statSampler.hpp"
    42 #ifdef TARGET_ARCH_x86
    43 # include "vm_version_x86.hpp"
    44 #endif
    45 #ifdef TARGET_ARCH_sparc
    46 # include "vm_version_sparc.hpp"
    47 #endif
    48 #ifdef TARGET_ARCH_zero
    49 # include "vm_version_zero.hpp"
    50 #endif
    51 #ifdef TARGET_ARCH_arm
    52 # include "vm_version_arm.hpp"
    53 #endif
    54 #ifdef TARGET_ARCH_ppc
    55 # include "vm_version_ppc.hpp"
    56 #endif
    57 #ifdef TARGET_ARCH_mips
    58 # include "vm_version_mips.hpp"
    59 #endif
    61 // --------------------------------------------------------
    62 // StatSamplerTask
    64 class StatSamplerTask : public PeriodicTask {
    65   public:
    66     StatSamplerTask(int interval_time) : PeriodicTask(interval_time) {}
    67     void task() { StatSampler::collect_sample(); }
    68 };
    71 //----------------------------------------------------------
    72 // Implementation of StatSampler
    74 StatSamplerTask*              StatSampler::_task   = NULL;
    75 PerfDataList*                 StatSampler::_sampled = NULL;
    77 /*
    78  * the initialize method is called from the engage() method
    79  * and is responsible for initializing various global variables.
    80  */
    81 void StatSampler::initialize() {
    83   if (!UsePerfData) return;
    85   // create performance data that could not be created prior
    86   // to vm_init_globals() or otherwise have no logical home.
    88   create_misc_perfdata();
    90   // get copy of the sampled list
    91   _sampled = PerfDataManager::sampled();
    93 }
    95 /*
    96  * The engage() method is called at initialization time via
    97  * Thread::create_vm() to initialize the StatSampler and
    98  * register it with the WatcherThread as a periodic task.
    99  */
   100 void StatSampler::engage() {
   102   if (!UsePerfData) return;
   104   if (!is_active()) {
   106     initialize();
   108     // start up the periodic task
   109     _task = new StatSamplerTask(PerfDataSamplingInterval);
   110     _task->enroll();
   111   }
   112 }
   115 /*
   116  * the disengage() method is responsible for deactivating the periodic
   117  * task and, if logging was enabled, for logging the final sample. This
   118  * method is called from before_exit() in java.cpp and is only called
   119  * after the WatcherThread has been stopped.
   120  */
   121 void StatSampler::disengage() {
   123   if (!UsePerfData) return;
   125   if (!is_active())
   126     return;
   128   // remove StatSamplerTask
   129   _task->disenroll();
   130   delete _task;
   131   _task = NULL;
   133   // force a final sample
   134   sample_data(_sampled);
   135 }
   137 /*
   138  * the destroy method is responsible for releasing any resources used by
   139  * the StatSampler prior to shutdown of the VM. this method is called from
   140  * before_exit() in java.cpp and is only called after the WatcherThread
   141  * has stopped.
   142  */
   143 void StatSampler::destroy() {
   145   if (!UsePerfData) return;
   147   if (_sampled != NULL) {
   148     delete(_sampled);
   149     _sampled = NULL;
   150   }
   151 }
   153 /*
   154  * The sample_data() method is responsible for sampling the
   155  * the data value for each PerfData instance in the given list.
   156  */
   157 void StatSampler::sample_data(PerfDataList* list) {
   159   assert(list != NULL, "null list unexpected");
   161   for (int index = 0; index < list->length(); index++) {
   162     PerfData* item = list->at(index);
   163     item->sample();
   164   }
   165 }
   167 /*
   168  * the collect_sample() method is the method invoked by the
   169  * WatcherThread via the PeriodicTask::task() method. This method
   170  * is responsible for collecting data samples from sampled
   171  * PerfData instances every PerfDataSamplingInterval milliseconds.
   172  * It is also responsible for logging the requested set of
   173  * PerfData instances every _sample_count milliseconds. While
   174  * logging data, it will output a column header after every _print_header
   175  * rows of data have been logged.
   176  */
   177 void StatSampler::collect_sample() {
   179   // future - check for new PerfData objects. PerfData objects might
   180   // get added to the PerfDataManager lists after we have already
   181   // built our local copies.
   182   //
   183   // if (PerfDataManager::count() > previous) {
   184   //   // get a new copy of the sampled list
   185   //   if (_sampled != NULL) {
   186   //     delete(_sampled);
   187   //     _sampled = NULL;
   188   //   }
   189   //   _sampled = PerfDataManager::sampled();
   190   // }
   192   assert(_sampled != NULL, "list not initialized");
   194   sample_data(_sampled);
   195 }
   197 /*
   198  * method to upcall into Java to return the value of the specified
   199  * property as a utf8 string, or NULL if does not exist. The caller
   200  * is responsible for setting a ResourceMark for proper cleanup of
   201  * the utf8 strings.
   202  */
   203 const char* StatSampler::get_system_property(const char* name, TRAPS) {
   205   // setup the arguments to getProperty
   206   Handle key_str   = java_lang_String::create_from_str(name, CHECK_NULL);
   208   // return value
   209   JavaValue result(T_OBJECT);
   211   // public static String getProperty(String key, String def);
   212   JavaCalls::call_static(&result,
   213                          KlassHandle(THREAD, SystemDictionary::System_klass()),
   214                          vmSymbols::getProperty_name(),
   215                          vmSymbols::string_string_signature(),
   216                          key_str,
   217                          CHECK_NULL);
   219   oop value_oop = (oop)result.get_jobject();
   220   if (value_oop == NULL) {
   221     return NULL;
   222   }
   224   // convert Java String to utf8 string
   225   char* value = java_lang_String::as_utf8_string(value_oop);
   227   return value;
   228 }
   230 /*
   231  * The list of System Properties that have corresponding PerfData
   232  * string instrumentation created by retrieving the named property's
   233  * value from System.getProperty() and unconditionally creating a
   234  * PerfStringConstant object initialized to the retreived value. This
   235  * is not an exhustive list of Java properties with corresponding string
   236  * instrumentation as the create_system_property_instrumentation() method
   237  * creates other property based instrumentation conditionally.
   238  */
   240 // stable interface, supported counters
   241 static const char* property_counters_ss[] = {
   242   "java.vm.specification.version",
   243   "java.vm.specification.name",
   244   "java.vm.specification.vendor",
   245   "java.vm.version",
   246   "java.vm.name",
   247   "java.vm.vendor",
   248   "java.vm.info",
   249   "java.library.path",
   250   "java.class.path",
   251   "java.endorsed.dirs",
   252   "java.ext.dirs",
   253   "java.version",
   254   "java.home",
   255   NULL
   256 };
   258 // unstable interface, supported counters
   259 static const char* property_counters_us[] = {
   260   NULL
   261 };
   263 // unstable interface, unsupported counters
   264 static const char* property_counters_uu[] = {
   265   "sun.boot.class.path",
   266   "sun.boot.library.path",
   267   NULL
   268 };
   270 typedef struct {
   271   const char** property_list;
   272   CounterNS name_space;
   273 } PropertyCounters;
   275 static PropertyCounters property_counters[] = {
   276   { property_counters_ss, JAVA_PROPERTY },
   277   { property_counters_us, COM_PROPERTY },
   278   { property_counters_uu, SUN_PROPERTY },
   279   { NULL, SUN_PROPERTY }
   280 };
   283 /*
   284  * Method to create PerfData string instruments that contain the values
   285  * of various system properties. String instruments are created for each
   286  * property specified in the property lists provided in property_counters[].
   287  * Property counters have a counter name space prefix prepended to the
   288  * property name as indicated in property_counters[].
   289  */
   290 void StatSampler::create_system_property_instrumentation(TRAPS) {
   292   ResourceMark rm;
   294   for (int i = 0; property_counters[i].property_list != NULL; i++) {
   296     for (int j = 0; property_counters[i].property_list[j] != NULL; j++) {
   298       const char* property_name = property_counters[i].property_list[j];
   299       assert(property_name != NULL, "property name should not be NULL");
   301       const char* value = get_system_property(property_name, CHECK);
   303       // the property must exist
   304       assert(value != NULL, "property name should be valid");
   306       if (value != NULL) {
   307         // create the property counter
   308         PerfDataManager::create_string_constant(property_counters[i].name_space,
   309                                                 property_name, value, CHECK);
   310       }
   311     }
   312   }
   313 }
   315 /*
   316  * The create_misc_perfdata() method provides a place to create
   317  * PerfData instances that would otherwise have no better place
   318  * to exist.
   319  */
   320 void StatSampler::create_misc_perfdata() {
   322   ResourceMark rm;
   323   EXCEPTION_MARK;
   325   // numeric constants
   327   // frequency of the native high resolution timer
   328   PerfDataManager::create_constant(SUN_OS, "hrt.frequency",
   329                                    PerfData::U_Hertz, os::elapsed_frequency(),
   330                                    CHECK);
   332   // string constants
   334   // create string instrumentation for various Java properties.
   335   create_system_property_instrumentation(CHECK);
   337   // hotspot flags (from .hotspotrc) and args (from command line)
   338   //
   339   PerfDataManager::create_string_constant(JAVA_RT, "vmFlags",
   340                                           Arguments::jvm_flags(), CHECK);
   341   PerfDataManager::create_string_constant(JAVA_RT, "vmArgs",
   342                                           Arguments::jvm_args(), CHECK);
   344   // java class name/jar file and arguments to main class
   345   // note: name is cooridnated with launcher and Arguments.cpp
   346   PerfDataManager::create_string_constant(SUN_RT, "javaCommand",
   347                                           Arguments::java_command(), CHECK);
   349   // the Java VM Internal version string
   350   PerfDataManager::create_string_constant(SUN_RT, "internalVersion",
   351                                          VM_Version::internal_vm_info_string(),
   352                                          CHECK);
   354   // create sampled instrumentation objects
   355   create_sampled_perfdata();
   356 }
   358 /*
   359  * helper class to provide for sampling of the elapsed_counter value
   360  * maintained in the OS class.
   361  */
   362 class HighResTimeSampler : public PerfSampleHelper {
   363   public:
   364     jlong take_sample() { return os::elapsed_counter(); }
   365 };
   367 /*
   368  * the create_sampled_perdata() method provides a place to instantiate
   369  * sampled PerfData instances that would otherwise have no better place
   370  * to exist.
   371  */
   372 void StatSampler::create_sampled_perfdata() {
   374   EXCEPTION_MARK;
   376   // setup sampling of the elapsed time counter maintained in the
   377   // the os class. This counter can be used as either a time stamp
   378   // for each logged entry or as a liveness indicator for the VM.
   379   PerfSampleHelper* psh = new HighResTimeSampler();
   380   PerfDataManager::create_counter(SUN_OS, "hrt.ticks",
   381                                   PerfData::U_Ticks, psh, CHECK);
   382 }
   384 /*
   385  * the statSampler_exit() function is called from os_init.cpp on
   386  * exit of the vm.
   387  */
   388 void statSampler_exit() {
   390   if (!UsePerfData) return;
   392   StatSampler::destroy();
   393 }

mercurial