|
1 /* |
|
2 * Copyright 2001-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 # include "incls/_precompiled.incl" |
|
26 # include "incls/_statSampler.cpp.incl" |
|
27 |
|
28 // -------------------------------------------------------- |
|
29 // StatSamplerTask |
|
30 |
|
31 class StatSamplerTask : public PeriodicTask { |
|
32 public: |
|
33 StatSamplerTask(int interval_time) : PeriodicTask(interval_time) {} |
|
34 void task() { StatSampler::collect_sample(); } |
|
35 }; |
|
36 |
|
37 |
|
38 //---------------------------------------------------------- |
|
39 // Implementation of StatSampler |
|
40 |
|
41 StatSamplerTask* StatSampler::_task = NULL; |
|
42 PerfDataList* StatSampler::_sampled = NULL; |
|
43 |
|
44 /* |
|
45 * the initialize method is called from the engage() method |
|
46 * and is responsible for initializing various global variables. |
|
47 */ |
|
48 void StatSampler::initialize() { |
|
49 |
|
50 if (!UsePerfData) return; |
|
51 |
|
52 // create performance data that could not be created prior |
|
53 // to vm_init_globals() or otherwise have no logical home. |
|
54 |
|
55 create_misc_perfdata(); |
|
56 |
|
57 // get copy of the sampled list |
|
58 _sampled = PerfDataManager::sampled(); |
|
59 |
|
60 } |
|
61 |
|
62 /* |
|
63 * The engage() method is called at initialization time via |
|
64 * Thread::create_vm() to initialize the StatSampler and |
|
65 * register it with the WatcherThread as a periodic task. |
|
66 */ |
|
67 void StatSampler::engage() { |
|
68 |
|
69 if (!UsePerfData) return; |
|
70 |
|
71 if (!is_active()) { |
|
72 |
|
73 initialize(); |
|
74 |
|
75 // start up the periodic task |
|
76 _task = new StatSamplerTask(PerfDataSamplingInterval); |
|
77 _task->enroll(); |
|
78 } |
|
79 } |
|
80 |
|
81 |
|
82 /* |
|
83 * the disengage() method is responsible for deactivating the periodic |
|
84 * task and, if logging was enabled, for logging the final sample. This |
|
85 * method is called from before_exit() in java.cpp and is only called |
|
86 * after the WatcherThread has been stopped. |
|
87 */ |
|
88 void StatSampler::disengage() { |
|
89 |
|
90 if (!UsePerfData) return; |
|
91 |
|
92 if (!is_active()) |
|
93 return; |
|
94 |
|
95 // remove StatSamplerTask |
|
96 _task->disenroll(); |
|
97 delete _task; |
|
98 _task = NULL; |
|
99 |
|
100 // force a final sample |
|
101 sample_data(_sampled); |
|
102 } |
|
103 |
|
104 /* |
|
105 * the destroy method is responsible for releasing any resources used by |
|
106 * the StatSampler prior to shutdown of the VM. this method is called from |
|
107 * before_exit() in java.cpp and is only called after the WatcherThread |
|
108 * has stopped. |
|
109 */ |
|
110 void StatSampler::destroy() { |
|
111 |
|
112 if (!UsePerfData) return; |
|
113 |
|
114 if (_sampled != NULL) { |
|
115 delete(_sampled); |
|
116 _sampled = NULL; |
|
117 } |
|
118 } |
|
119 |
|
120 /* |
|
121 * The sample_data() method is responsible for sampling the |
|
122 * the data value for each PerfData instance in the given list. |
|
123 */ |
|
124 void StatSampler::sample_data(PerfDataList* list) { |
|
125 |
|
126 assert(list != NULL, "null list unexpected"); |
|
127 |
|
128 for (int index = 0; index < list->length(); index++) { |
|
129 PerfData* item = list->at(index); |
|
130 item->sample(); |
|
131 } |
|
132 } |
|
133 |
|
134 /* |
|
135 * the collect_sample() method is the method invoked by the |
|
136 * WatcherThread via the PeriodicTask::task() method. This method |
|
137 * is responsible for collecting data samples from sampled |
|
138 * PerfData instances every PerfDataSamplingInterval milliseconds. |
|
139 * It is also responsible for logging the requested set of |
|
140 * PerfData instances every _sample_count milliseconds. While |
|
141 * logging data, it will output a column header after every _print_header |
|
142 * rows of data have been logged. |
|
143 */ |
|
144 void StatSampler::collect_sample() { |
|
145 |
|
146 // future - check for new PerfData objects. PerfData objects might |
|
147 // get added to the PerfDataManager lists after we have already |
|
148 // built our local copies. |
|
149 // |
|
150 // if (PerfDataManager::count() > previous) { |
|
151 // // get a new copy of the sampled list |
|
152 // if (_sampled != NULL) { |
|
153 // delete(_sampled); |
|
154 // _sampled = NULL; |
|
155 // } |
|
156 // _sampled = PerfDataManager::sampled(); |
|
157 // } |
|
158 |
|
159 assert(_sampled != NULL, "list not initialized"); |
|
160 |
|
161 sample_data(_sampled); |
|
162 } |
|
163 |
|
164 /* |
|
165 * method to upcall into Java to return the value of the specified |
|
166 * property as a utf8 string, or NULL if does not exist. The caller |
|
167 * is responsible for setting a ResourceMark for proper cleanup of |
|
168 * the utf8 strings. |
|
169 */ |
|
170 const char* StatSampler::get_system_property(const char* name, TRAPS) { |
|
171 |
|
172 // setup the arguments to getProperty |
|
173 Handle key_str = java_lang_String::create_from_str(name, CHECK_NULL); |
|
174 |
|
175 // return value |
|
176 JavaValue result(T_OBJECT); |
|
177 |
|
178 // public static String getProperty(String key, String def); |
|
179 JavaCalls::call_static(&result, |
|
180 KlassHandle(THREAD, SystemDictionary::system_klass()), |
|
181 vmSymbolHandles::getProperty_name(), |
|
182 vmSymbolHandles::string_string_signature(), |
|
183 key_str, |
|
184 CHECK_NULL); |
|
185 |
|
186 oop value_oop = (oop)result.get_jobject(); |
|
187 if (value_oop == NULL) { |
|
188 return NULL; |
|
189 } |
|
190 |
|
191 // convert Java String to utf8 string |
|
192 char* value = java_lang_String::as_utf8_string(value_oop); |
|
193 |
|
194 return value; |
|
195 } |
|
196 |
|
197 /* |
|
198 * The list of System Properties that have corresponding PerfData |
|
199 * string instrumentation created by retrieving the named property's |
|
200 * value from System.getProperty() and unconditionally creating a |
|
201 * PerfStringConstant object initialized to the retreived value. This |
|
202 * is not an exhustive list of Java properties with corresponding string |
|
203 * instrumentation as the create_system_property_instrumentation() method |
|
204 * creates other property based instrumentation conditionally. |
|
205 */ |
|
206 |
|
207 // stable interface, supported counters |
|
208 static const char* property_counters_ss[] = { |
|
209 "java.vm.specification.version", |
|
210 "java.vm.specification.name", |
|
211 "java.vm.specification.vendor", |
|
212 "java.vm.version", |
|
213 "java.vm.name", |
|
214 "java.vm.vendor", |
|
215 "java.vm.info", |
|
216 "java.library.path", |
|
217 "java.class.path", |
|
218 "java.endorsed.dirs", |
|
219 "java.ext.dirs", |
|
220 "java.home", |
|
221 NULL |
|
222 }; |
|
223 |
|
224 // unstable interface, supported counters |
|
225 static const char* property_counters_us[] = { |
|
226 NULL |
|
227 }; |
|
228 |
|
229 // unstable interface, unsupported counters |
|
230 static const char* property_counters_uu[] = { |
|
231 "sun.boot.class.path", |
|
232 "sun.boot.library.path", |
|
233 NULL |
|
234 }; |
|
235 |
|
236 typedef struct { |
|
237 const char** property_list; |
|
238 CounterNS name_space; |
|
239 } PropertyCounters; |
|
240 |
|
241 static PropertyCounters property_counters[] = { |
|
242 { property_counters_ss, JAVA_PROPERTY }, |
|
243 { property_counters_us, COM_PROPERTY }, |
|
244 { property_counters_uu, SUN_PROPERTY }, |
|
245 { NULL, SUN_PROPERTY } |
|
246 }; |
|
247 |
|
248 |
|
249 /* |
|
250 * Method to create PerfData string instruments that contain the values |
|
251 * of various system properties. String instruments are created for each |
|
252 * property specified in the property lists provided in property_counters[]. |
|
253 * Property counters have a counter name space prefix prepended to the |
|
254 * property name as indicated in property_counters[]. |
|
255 */ |
|
256 void StatSampler::create_system_property_instrumentation(TRAPS) { |
|
257 |
|
258 ResourceMark rm; |
|
259 |
|
260 for (int i = 0; property_counters[i].property_list != NULL; i++) { |
|
261 |
|
262 for (int j = 0; property_counters[i].property_list[j] != NULL; j++) { |
|
263 |
|
264 const char* property_name = property_counters[i].property_list[j]; |
|
265 assert(property_name != NULL, "property name should not be NULL"); |
|
266 |
|
267 const char* value = get_system_property(property_name, CHECK); |
|
268 |
|
269 // the property must exist |
|
270 assert(value != NULL, "property name should be valid"); |
|
271 |
|
272 if (value != NULL) { |
|
273 // create the property counter |
|
274 PerfDataManager::create_string_constant(property_counters[i].name_space, |
|
275 property_name, value, CHECK); |
|
276 } |
|
277 } |
|
278 } |
|
279 } |
|
280 |
|
281 /* |
|
282 * The create_misc_perfdata() method provides a place to create |
|
283 * PerfData instances that would otherwise have no better place |
|
284 * to exist. |
|
285 */ |
|
286 void StatSampler::create_misc_perfdata() { |
|
287 |
|
288 ResourceMark rm; |
|
289 EXCEPTION_MARK; |
|
290 |
|
291 // numeric constants |
|
292 |
|
293 // frequency of the native high resolution timer |
|
294 PerfDataManager::create_constant(SUN_OS, "hrt.frequency", |
|
295 PerfData::U_Hertz, os::elapsed_frequency(), |
|
296 CHECK); |
|
297 |
|
298 // string constants |
|
299 |
|
300 // create string instrumentation for various Java properties. |
|
301 create_system_property_instrumentation(CHECK); |
|
302 |
|
303 // hotspot flags (from .hotspotrc) and args (from command line) |
|
304 // |
|
305 PerfDataManager::create_string_constant(JAVA_RT, "vmFlags", |
|
306 Arguments::jvm_flags(), CHECK); |
|
307 PerfDataManager::create_string_constant(JAVA_RT, "vmArgs", |
|
308 Arguments::jvm_args(), CHECK); |
|
309 |
|
310 // java class name/jar file and arguments to main class |
|
311 // note: name is cooridnated with launcher and Arguments.cpp |
|
312 PerfDataManager::create_string_constant(SUN_RT, "javaCommand", |
|
313 Arguments::java_command(), CHECK); |
|
314 |
|
315 // the Java VM Internal version string |
|
316 PerfDataManager::create_string_constant(SUN_RT, "internalVersion", |
|
317 VM_Version::internal_vm_info_string(), |
|
318 CHECK); |
|
319 |
|
320 // create sampled instrumentation objects |
|
321 create_sampled_perfdata(); |
|
322 } |
|
323 |
|
324 /* |
|
325 * helper class to provide for sampling of the elapsed_counter value |
|
326 * maintained in the OS class. |
|
327 */ |
|
328 class HighResTimeSampler : public PerfSampleHelper { |
|
329 public: |
|
330 jlong take_sample() { return os::elapsed_counter(); } |
|
331 }; |
|
332 |
|
333 /* |
|
334 * the create_sampled_perdata() method provides a place to instantiate |
|
335 * sampled PerfData instances that would otherwise have no better place |
|
336 * to exist. |
|
337 */ |
|
338 void StatSampler::create_sampled_perfdata() { |
|
339 |
|
340 EXCEPTION_MARK; |
|
341 |
|
342 // setup sampling of the elapsed time counter maintained in the |
|
343 // the os class. This counter can be used as either a time stamp |
|
344 // for each logged entry or as a liveness indicator for the VM. |
|
345 PerfSampleHelper* psh = new HighResTimeSampler(); |
|
346 PerfDataManager::create_counter(SUN_OS, "hrt.ticks", |
|
347 PerfData::U_Ticks, psh, CHECK); |
|
348 } |
|
349 |
|
350 /* |
|
351 * the statSampler_exit() function is called from os_init.cpp on |
|
352 * exit of the vm. |
|
353 */ |
|
354 void statSampler_exit() { |
|
355 |
|
356 if (!UsePerfData) return; |
|
357 |
|
358 StatSampler::destroy(); |
|
359 } |