Tue, 08 Aug 2017 15:57:29 +0800
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 }