0
|
1 /*
|
|
2 * Copyright 2003-2007 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/_management.cpp.incl"
|
|
27
|
|
28 PerfVariable* Management::_begin_vm_creation_time = NULL;
|
|
29 PerfVariable* Management::_end_vm_creation_time = NULL;
|
|
30 PerfVariable* Management::_vm_init_done_time = NULL;
|
|
31
|
|
32 klassOop Management::_sensor_klass = NULL;
|
|
33 klassOop Management::_threadInfo_klass = NULL;
|
|
34 klassOop Management::_memoryUsage_klass = NULL;
|
|
35 klassOop Management::_memoryPoolMXBean_klass = NULL;
|
|
36 klassOop Management::_memoryManagerMXBean_klass = NULL;
|
|
37 klassOop Management::_garbageCollectorMXBean_klass = NULL;
|
|
38 klassOop Management::_managementFactory_klass = NULL;
|
|
39
|
|
40 jmmOptionalSupport Management::_optional_support = {0};
|
|
41 TimeStamp Management::_stamp;
|
|
42
|
|
43 void management_init() {
|
|
44 Management::init();
|
|
45 ThreadService::init();
|
|
46 RuntimeService::init();
|
|
47 ClassLoadingService::init();
|
|
48 }
|
|
49
|
|
50 void Management::init() {
|
|
51 EXCEPTION_MARK;
|
|
52
|
|
53 // These counters are for java.lang.management API support.
|
|
54 // They are created even if -XX:-UsePerfData is set and in
|
|
55 // that case, they will be allocated on C heap.
|
|
56
|
|
57 _begin_vm_creation_time =
|
|
58 PerfDataManager::create_variable(SUN_RT, "createVmBeginTime",
|
|
59 PerfData::U_None, CHECK);
|
|
60
|
|
61 _end_vm_creation_time =
|
|
62 PerfDataManager::create_variable(SUN_RT, "createVmEndTime",
|
|
63 PerfData::U_None, CHECK);
|
|
64
|
|
65 _vm_init_done_time =
|
|
66 PerfDataManager::create_variable(SUN_RT, "vmInitDoneTime",
|
|
67 PerfData::U_None, CHECK);
|
|
68
|
|
69 // Initialize optional support
|
|
70 _optional_support.isLowMemoryDetectionSupported = 1;
|
|
71 _optional_support.isCompilationTimeMonitoringSupported = 1;
|
|
72 _optional_support.isThreadContentionMonitoringSupported = 1;
|
|
73
|
|
74 if (os::is_thread_cpu_time_supported()) {
|
|
75 _optional_support.isCurrentThreadCpuTimeSupported = 1;
|
|
76 _optional_support.isOtherThreadCpuTimeSupported = 1;
|
|
77 } else {
|
|
78 _optional_support.isCurrentThreadCpuTimeSupported = 0;
|
|
79 _optional_support.isOtherThreadCpuTimeSupported = 0;
|
|
80 }
|
|
81 _optional_support.isBootClassPathSupported = 1;
|
|
82 _optional_support.isObjectMonitorUsageSupported = 1;
|
|
83 #ifndef SERVICES_KERNEL
|
|
84 // This depends on the heap inspector
|
|
85 _optional_support.isSynchronizerUsageSupported = 1;
|
|
86 #endif // SERVICES_KERNEL
|
|
87 }
|
|
88
|
|
89 void Management::initialize(TRAPS) {
|
|
90 // Start the low memory detector thread
|
|
91 LowMemoryDetector::initialize();
|
|
92
|
|
93 if (ManagementServer) {
|
|
94 ResourceMark rm(THREAD);
|
|
95 HandleMark hm(THREAD);
|
|
96
|
|
97 // Load and initialize the sun.management.Agent class
|
|
98 // invoke startAgent method to start the management server
|
|
99 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
|
|
100 klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::sun_management_Agent(),
|
|
101 loader,
|
|
102 Handle(),
|
|
103 true,
|
|
104 CHECK);
|
|
105 instanceKlassHandle ik (THREAD, k);
|
|
106
|
|
107 JavaValue result(T_VOID);
|
|
108 JavaCalls::call_static(&result,
|
|
109 ik,
|
|
110 vmSymbolHandles::startAgent_name(),
|
|
111 vmSymbolHandles::void_method_signature(),
|
|
112 CHECK);
|
|
113 }
|
|
114 }
|
|
115
|
|
116 void Management::get_optional_support(jmmOptionalSupport* support) {
|
|
117 memcpy(support, &_optional_support, sizeof(jmmOptionalSupport));
|
|
118 }
|
|
119
|
|
120 klassOop Management::load_and_initialize_klass(symbolHandle sh, TRAPS) {
|
|
121 klassOop k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL);
|
|
122 instanceKlassHandle ik (THREAD, k);
|
|
123 if (ik->should_be_initialized()) {
|
|
124 ik->initialize(CHECK_NULL);
|
|
125 }
|
|
126 return ik();
|
|
127 }
|
|
128
|
|
129 void Management::record_vm_startup_time(jlong begin, jlong duration) {
|
|
130 // if the performance counter is not initialized,
|
|
131 // then vm initialization failed; simply return.
|
|
132 if (_begin_vm_creation_time == NULL) return;
|
|
133
|
|
134 _begin_vm_creation_time->set_value(begin);
|
|
135 _end_vm_creation_time->set_value(begin + duration);
|
|
136 PerfMemory::set_accessible(true);
|
|
137 }
|
|
138
|
|
139 jlong Management::timestamp() {
|
|
140 TimeStamp t;
|
|
141 t.update();
|
|
142 return t.ticks() - _stamp.ticks();
|
|
143 }
|
|
144
|
|
145 void Management::oops_do(OopClosure* f) {
|
|
146 MemoryService::oops_do(f);
|
|
147 ThreadService::oops_do(f);
|
|
148
|
|
149 f->do_oop((oop*) &_sensor_klass);
|
|
150 f->do_oop((oop*) &_threadInfo_klass);
|
|
151 f->do_oop((oop*) &_memoryUsage_klass);
|
|
152 f->do_oop((oop*) &_memoryPoolMXBean_klass);
|
|
153 f->do_oop((oop*) &_memoryManagerMXBean_klass);
|
|
154 f->do_oop((oop*) &_garbageCollectorMXBean_klass);
|
|
155 f->do_oop((oop*) &_managementFactory_klass);
|
|
156 }
|
|
157
|
|
158 klassOop Management::java_lang_management_ThreadInfo_klass(TRAPS) {
|
|
159 if (_threadInfo_klass == NULL) {
|
|
160 _threadInfo_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_ThreadInfo(), CHECK_NULL);
|
|
161 }
|
|
162 return _threadInfo_klass;
|
|
163 }
|
|
164
|
|
165 klassOop Management::java_lang_management_MemoryUsage_klass(TRAPS) {
|
|
166 if (_memoryUsage_klass == NULL) {
|
|
167 _memoryUsage_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_MemoryUsage(), CHECK_NULL);
|
|
168 }
|
|
169 return _memoryUsage_klass;
|
|
170 }
|
|
171
|
|
172 klassOop Management::java_lang_management_MemoryPoolMXBean_klass(TRAPS) {
|
|
173 if (_memoryPoolMXBean_klass == NULL) {
|
|
174 _memoryPoolMXBean_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_MemoryPoolMXBean(), CHECK_NULL);
|
|
175 }
|
|
176 return _memoryPoolMXBean_klass;
|
|
177 }
|
|
178
|
|
179 klassOop Management::java_lang_management_MemoryManagerMXBean_klass(TRAPS) {
|
|
180 if (_memoryManagerMXBean_klass == NULL) {
|
|
181 _memoryManagerMXBean_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_MemoryManagerMXBean(), CHECK_NULL);
|
|
182 }
|
|
183 return _memoryManagerMXBean_klass;
|
|
184 }
|
|
185
|
|
186 klassOop Management::java_lang_management_GarbageCollectorMXBean_klass(TRAPS) {
|
|
187 if (_garbageCollectorMXBean_klass == NULL) {
|
|
188 _garbageCollectorMXBean_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_GarbageCollectorMXBean(), CHECK_NULL);
|
|
189 }
|
|
190 return _garbageCollectorMXBean_klass;
|
|
191 }
|
|
192
|
|
193 klassOop Management::sun_management_Sensor_klass(TRAPS) {
|
|
194 if (_sensor_klass == NULL) {
|
|
195 _sensor_klass = load_and_initialize_klass(vmSymbolHandles::sun_management_Sensor(), CHECK_NULL);
|
|
196 }
|
|
197 return _sensor_klass;
|
|
198 }
|
|
199
|
|
200 klassOop Management::sun_management_ManagementFactory_klass(TRAPS) {
|
|
201 if (_managementFactory_klass == NULL) {
|
|
202 _managementFactory_klass = load_and_initialize_klass(vmSymbolHandles::sun_management_ManagementFactory(), CHECK_NULL);
|
|
203 }
|
|
204 return _managementFactory_klass;
|
|
205 }
|
|
206
|
|
207 static void initialize_ThreadInfo_constructor_arguments(JavaCallArguments* args, ThreadSnapshot* snapshot, TRAPS) {
|
|
208 Handle snapshot_thread(THREAD, snapshot->threadObj());
|
|
209
|
|
210 jlong contended_time;
|
|
211 jlong waited_time;
|
|
212 if (ThreadService::is_thread_monitoring_contention()) {
|
|
213 contended_time = Management::ticks_to_ms(snapshot->contended_enter_ticks());
|
|
214 waited_time = Management::ticks_to_ms(snapshot->monitor_wait_ticks() + snapshot->sleep_ticks());
|
|
215 } else {
|
|
216 // set them to -1 if thread contention monitoring is disabled.
|
|
217 contended_time = max_julong;
|
|
218 waited_time = max_julong;
|
|
219 }
|
|
220
|
|
221 int thread_status = snapshot->thread_status();
|
|
222 assert((thread_status & JMM_THREAD_STATE_FLAG_MASK) == 0, "Flags already set in thread_status in Thread object");
|
|
223 if (snapshot->is_ext_suspended()) {
|
|
224 thread_status |= JMM_THREAD_STATE_FLAG_SUSPENDED;
|
|
225 }
|
|
226 if (snapshot->is_in_native()) {
|
|
227 thread_status |= JMM_THREAD_STATE_FLAG_NATIVE;
|
|
228 }
|
|
229
|
|
230 ThreadStackTrace* st = snapshot->get_stack_trace();
|
|
231 Handle stacktrace_h;
|
|
232 if (st != NULL) {
|
|
233 stacktrace_h = st->allocate_fill_stack_trace_element_array(CHECK);
|
|
234 } else {
|
|
235 stacktrace_h = Handle();
|
|
236 }
|
|
237
|
|
238 args->push_oop(snapshot_thread);
|
|
239 args->push_int(thread_status);
|
|
240 args->push_oop(Handle(THREAD, snapshot->blocker_object()));
|
|
241 args->push_oop(Handle(THREAD, snapshot->blocker_object_owner()));
|
|
242 args->push_long(snapshot->contended_enter_count());
|
|
243 args->push_long(contended_time);
|
|
244 args->push_long(snapshot->monitor_wait_count() + snapshot->sleep_count());
|
|
245 args->push_long(waited_time);
|
|
246 args->push_oop(stacktrace_h);
|
|
247 }
|
|
248
|
|
249 // Helper function to construct a ThreadInfo object
|
|
250 instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot, TRAPS) {
|
|
251 klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
|
|
252 instanceKlassHandle ik (THREAD, k);
|
|
253
|
|
254 JavaValue result(T_VOID);
|
|
255 JavaCallArguments args(14);
|
|
256
|
|
257 // First allocate a ThreadObj object and
|
|
258 // push the receiver as the first argument
|
|
259 Handle element = ik->allocate_instance_handle(CHECK_NULL);
|
|
260 args.push_oop(element);
|
|
261
|
|
262 // initialize the arguments for the ThreadInfo constructor
|
|
263 initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL);
|
|
264
|
|
265 // Call ThreadInfo constructor with no locked monitors and synchronizers
|
|
266 JavaCalls::call_special(&result,
|
|
267 ik,
|
|
268 vmSymbolHandles::object_initializer_name(),
|
|
269 vmSymbolHandles::java_lang_management_ThreadInfo_constructor_signature(),
|
|
270 &args,
|
|
271 CHECK_NULL);
|
|
272
|
|
273 return (instanceOop) element();
|
|
274 }
|
|
275
|
|
276 instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot,
|
|
277 objArrayHandle monitors_array,
|
|
278 typeArrayHandle depths_array,
|
|
279 objArrayHandle synchronizers_array,
|
|
280 TRAPS) {
|
|
281 klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
|
|
282 instanceKlassHandle ik (THREAD, k);
|
|
283
|
|
284 JavaValue result(T_VOID);
|
|
285 JavaCallArguments args(17);
|
|
286
|
|
287 // First allocate a ThreadObj object and
|
|
288 // push the receiver as the first argument
|
|
289 Handle element = ik->allocate_instance_handle(CHECK_NULL);
|
|
290 args.push_oop(element);
|
|
291
|
|
292 // initialize the arguments for the ThreadInfo constructor
|
|
293 initialize_ThreadInfo_constructor_arguments(&args, snapshot, CHECK_NULL);
|
|
294
|
|
295 // push the locked monitors and synchronizers in the arguments
|
|
296 args.push_oop(monitors_array);
|
|
297 args.push_oop(depths_array);
|
|
298 args.push_oop(synchronizers_array);
|
|
299
|
|
300 // Call ThreadInfo constructor with locked monitors and synchronizers
|
|
301 JavaCalls::call_special(&result,
|
|
302 ik,
|
|
303 vmSymbolHandles::object_initializer_name(),
|
|
304 vmSymbolHandles::java_lang_management_ThreadInfo_with_locks_constructor_signature(),
|
|
305 &args,
|
|
306 CHECK_NULL);
|
|
307
|
|
308 return (instanceOop) element();
|
|
309 }
|
|
310
|
|
311 // Helper functions
|
|
312 static JavaThread* find_java_thread_from_id(jlong thread_id) {
|
|
313 assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
|
|
314
|
|
315 JavaThread* java_thread = NULL;
|
|
316 // Sequential search for now. Need to do better optimization later.
|
|
317 for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
|
|
318 oop tobj = thread->threadObj();
|
|
319 if (!thread->is_exiting() &&
|
|
320 tobj != NULL &&
|
|
321 thread_id == java_lang_Thread::thread_id(tobj)) {
|
|
322 java_thread = thread;
|
|
323 break;
|
|
324 }
|
|
325 }
|
|
326 return java_thread;
|
|
327 }
|
|
328
|
|
329 static GCMemoryManager* get_gc_memory_manager_from_jobject(jobject mgr, TRAPS) {
|
|
330 if (mgr == NULL) {
|
|
331 THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
|
|
332 }
|
|
333 oop mgr_obj = JNIHandles::resolve(mgr);
|
|
334 instanceHandle h(THREAD, (instanceOop) mgr_obj);
|
|
335
|
|
336 klassOop k = Management::java_lang_management_GarbageCollectorMXBean_klass(CHECK_NULL);
|
|
337 if (!h->is_a(k)) {
|
|
338 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
339 "the object is not an instance of java.lang.management.GarbageCollectorMXBean class",
|
|
340 NULL);
|
|
341 }
|
|
342
|
|
343 MemoryManager* gc = MemoryService::get_memory_manager(h);
|
|
344 if (gc == NULL || !gc->is_gc_memory_manager()) {
|
|
345 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
346 "Invalid GC memory manager",
|
|
347 NULL);
|
|
348 }
|
|
349 return (GCMemoryManager*) gc;
|
|
350 }
|
|
351
|
|
352 static MemoryPool* get_memory_pool_from_jobject(jobject obj, TRAPS) {
|
|
353 if (obj == NULL) {
|
|
354 THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
|
|
355 }
|
|
356
|
|
357 oop pool_obj = JNIHandles::resolve(obj);
|
|
358 assert(pool_obj->is_instance(), "Should be an instanceOop");
|
|
359 instanceHandle ph(THREAD, (instanceOop) pool_obj);
|
|
360
|
|
361 return MemoryService::get_memory_pool(ph);
|
|
362 }
|
|
363
|
|
364 static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
|
|
365 int num_threads = ids_ah->length();
|
|
366 // should be non-empty array
|
|
367 if (num_threads == 0) {
|
|
368 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
|
369 "Empty array of thread IDs");
|
|
370 }
|
|
371
|
|
372 // Validate input thread IDs
|
|
373 int i = 0;
|
|
374 for (i = 0; i < num_threads; i++) {
|
|
375 jlong tid = ids_ah->long_at(i);
|
|
376 if (tid <= 0) {
|
|
377 // throw exception if invalid thread id.
|
|
378 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
|
379 "Invalid thread ID entry");
|
|
380 }
|
|
381 }
|
|
382
|
|
383 }
|
|
384
|
|
385 static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
|
|
386
|
|
387 // check if the element of infoArray is of type ThreadInfo class
|
|
388 klassOop threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK);
|
|
389 klassOop element_klass = objArrayKlass::cast(infoArray_h->klass())->element_klass();
|
|
390 if (element_klass != threadinfo_klass) {
|
|
391 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
|
392 "infoArray element type is not ThreadInfo class");
|
|
393 }
|
|
394
|
|
395 }
|
|
396
|
|
397
|
|
398 static MemoryManager* get_memory_manager_from_jobject(jobject obj, TRAPS) {
|
|
399 if (obj == NULL) {
|
|
400 THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
|
|
401 }
|
|
402
|
|
403 oop mgr_obj = JNIHandles::resolve(obj);
|
|
404 assert(mgr_obj->is_instance(), "Should be an instanceOop");
|
|
405 instanceHandle mh(THREAD, (instanceOop) mgr_obj);
|
|
406
|
|
407 return MemoryService::get_memory_manager(mh);
|
|
408 }
|
|
409
|
|
410 // Returns a version string and sets major and minor version if
|
|
411 // the input parameters are non-null.
|
|
412 JVM_LEAF(jint, jmm_GetVersion(JNIEnv *env))
|
|
413 return JMM_VERSION;
|
|
414 JVM_END
|
|
415
|
|
416 // Gets the list of VM monitoring and management optional supports
|
|
417 // Returns 0 if succeeded; otherwise returns non-zero.
|
|
418 JVM_LEAF(jint, jmm_GetOptionalSupport(JNIEnv *env, jmmOptionalSupport* support))
|
|
419 if (support == NULL) {
|
|
420 return -1;
|
|
421 }
|
|
422 Management::get_optional_support(support);
|
|
423 return 0;
|
|
424 JVM_END
|
|
425
|
|
426 // Returns a java.lang.String object containing the input arguments to the VM.
|
|
427 JVM_ENTRY(jobject, jmm_GetInputArguments(JNIEnv *env))
|
|
428 ResourceMark rm(THREAD);
|
|
429
|
|
430 if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) {
|
|
431 return NULL;
|
|
432 }
|
|
433
|
|
434 char** vm_flags = Arguments::jvm_flags_array();
|
|
435 char** vm_args = Arguments::jvm_args_array();
|
|
436 int num_flags = Arguments::num_jvm_flags();
|
|
437 int num_args = Arguments::num_jvm_args();
|
|
438
|
|
439 size_t length = 1; // null terminator
|
|
440 int i;
|
|
441 for (i = 0; i < num_flags; i++) {
|
|
442 length += strlen(vm_flags[i]);
|
|
443 }
|
|
444 for (i = 0; i < num_args; i++) {
|
|
445 length += strlen(vm_args[i]);
|
|
446 }
|
|
447 // add a space between each argument
|
|
448 length += num_flags + num_args - 1;
|
|
449
|
|
450 // Return the list of input arguments passed to the VM
|
|
451 // and preserve the order that the VM processes.
|
|
452 char* args = NEW_RESOURCE_ARRAY(char, length);
|
|
453 args[0] = '\0';
|
|
454 // concatenate all jvm_flags
|
|
455 if (num_flags > 0) {
|
|
456 strcat(args, vm_flags[0]);
|
|
457 for (i = 1; i < num_flags; i++) {
|
|
458 strcat(args, " ");
|
|
459 strcat(args, vm_flags[i]);
|
|
460 }
|
|
461 }
|
|
462
|
|
463 if (num_args > 0 && num_flags > 0) {
|
|
464 // append a space if args already contains one or more jvm_flags
|
|
465 strcat(args, " ");
|
|
466 }
|
|
467
|
|
468 // concatenate all jvm_args
|
|
469 if (num_args > 0) {
|
|
470 strcat(args, vm_args[0]);
|
|
471 for (i = 1; i < num_args; i++) {
|
|
472 strcat(args, " ");
|
|
473 strcat(args, vm_args[i]);
|
|
474 }
|
|
475 }
|
|
476
|
|
477 Handle hargs = java_lang_String::create_from_platform_dependent_str(args, CHECK_NULL);
|
|
478 return JNIHandles::make_local(env, hargs());
|
|
479 JVM_END
|
|
480
|
|
481 // Returns an array of java.lang.String object containing the input arguments to the VM.
|
|
482 JVM_ENTRY(jobjectArray, jmm_GetInputArgumentArray(JNIEnv *env))
|
|
483 ResourceMark rm(THREAD);
|
|
484
|
|
485 if (Arguments::num_jvm_args() == 0 && Arguments::num_jvm_flags() == 0) {
|
|
486 return NULL;
|
|
487 }
|
|
488
|
|
489 char** vm_flags = Arguments::jvm_flags_array();
|
|
490 char** vm_args = Arguments::jvm_args_array();
|
|
491 int num_flags = Arguments::num_jvm_flags();
|
|
492 int num_args = Arguments::num_jvm_args();
|
|
493
|
|
494 instanceKlassHandle ik (THREAD, SystemDictionary::string_klass());
|
|
495 objArrayOop r = oopFactory::new_objArray(ik(), num_args + num_flags, CHECK_NULL);
|
|
496 objArrayHandle result_h(THREAD, r);
|
|
497
|
|
498 int index = 0;
|
|
499 for (int j = 0; j < num_flags; j++, index++) {
|
|
500 Handle h = java_lang_String::create_from_platform_dependent_str(vm_flags[j], CHECK_NULL);
|
|
501 result_h->obj_at_put(index, h());
|
|
502 }
|
|
503 for (int i = 0; i < num_args; i++, index++) {
|
|
504 Handle h = java_lang_String::create_from_platform_dependent_str(vm_args[i], CHECK_NULL);
|
|
505 result_h->obj_at_put(index, h());
|
|
506 }
|
|
507 return (jobjectArray) JNIHandles::make_local(env, result_h());
|
|
508 JVM_END
|
|
509
|
|
510 // Returns an array of java/lang/management/MemoryPoolMXBean object
|
|
511 // one for each memory pool if obj == null; otherwise returns
|
|
512 // an array of memory pools for a given memory manager if
|
|
513 // it is a valid memory manager.
|
|
514 JVM_ENTRY(jobjectArray, jmm_GetMemoryPools(JNIEnv* env, jobject obj))
|
|
515 ResourceMark rm(THREAD);
|
|
516
|
|
517 int num_memory_pools;
|
|
518 MemoryManager* mgr = NULL;
|
|
519 if (obj == NULL) {
|
|
520 num_memory_pools = MemoryService::num_memory_pools();
|
|
521 } else {
|
|
522 mgr = get_memory_manager_from_jobject(obj, CHECK_NULL);
|
|
523 if (mgr == NULL) {
|
|
524 return NULL;
|
|
525 }
|
|
526 num_memory_pools = mgr->num_memory_pools();
|
|
527 }
|
|
528
|
|
529 // Allocate the resulting MemoryPoolMXBean[] object
|
|
530 klassOop k = Management::java_lang_management_MemoryPoolMXBean_klass(CHECK_NULL);
|
|
531 instanceKlassHandle ik (THREAD, k);
|
|
532 objArrayOop r = oopFactory::new_objArray(ik(), num_memory_pools, CHECK_NULL);
|
|
533 objArrayHandle poolArray(THREAD, r);
|
|
534
|
|
535 if (mgr == NULL) {
|
|
536 // Get all memory pools
|
|
537 for (int i = 0; i < num_memory_pools; i++) {
|
|
538 MemoryPool* pool = MemoryService::get_memory_pool(i);
|
|
539 instanceOop p = pool->get_memory_pool_instance(CHECK_NULL);
|
|
540 instanceHandle ph(THREAD, p);
|
|
541 poolArray->obj_at_put(i, ph());
|
|
542 }
|
|
543 } else {
|
|
544 // Get memory pools managed by a given memory manager
|
|
545 for (int i = 0; i < num_memory_pools; i++) {
|
|
546 MemoryPool* pool = mgr->get_memory_pool(i);
|
|
547 instanceOop p = pool->get_memory_pool_instance(CHECK_NULL);
|
|
548 instanceHandle ph(THREAD, p);
|
|
549 poolArray->obj_at_put(i, ph());
|
|
550 }
|
|
551 }
|
|
552 return (jobjectArray) JNIHandles::make_local(env, poolArray());
|
|
553 JVM_END
|
|
554
|
|
555 // Returns an array of java/lang/management/MemoryManagerMXBean object
|
|
556 // one for each memory manager if obj == null; otherwise returns
|
|
557 // an array of memory managers for a given memory pool if
|
|
558 // it is a valid memory pool.
|
|
559 JVM_ENTRY(jobjectArray, jmm_GetMemoryManagers(JNIEnv* env, jobject obj))
|
|
560 ResourceMark rm(THREAD);
|
|
561
|
|
562 int num_mgrs;
|
|
563 MemoryPool* pool = NULL;
|
|
564 if (obj == NULL) {
|
|
565 num_mgrs = MemoryService::num_memory_managers();
|
|
566 } else {
|
|
567 pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
|
|
568 if (pool == NULL) {
|
|
569 return NULL;
|
|
570 }
|
|
571 num_mgrs = pool->num_memory_managers();
|
|
572 }
|
|
573
|
|
574 // Allocate the resulting MemoryManagerMXBean[] object
|
|
575 klassOop k = Management::java_lang_management_MemoryManagerMXBean_klass(CHECK_NULL);
|
|
576 instanceKlassHandle ik (THREAD, k);
|
|
577 objArrayOop r = oopFactory::new_objArray(ik(), num_mgrs, CHECK_NULL);
|
|
578 objArrayHandle mgrArray(THREAD, r);
|
|
579
|
|
580 if (pool == NULL) {
|
|
581 // Get all memory managers
|
|
582 for (int i = 0; i < num_mgrs; i++) {
|
|
583 MemoryManager* mgr = MemoryService::get_memory_manager(i);
|
|
584 instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL);
|
|
585 instanceHandle ph(THREAD, p);
|
|
586 mgrArray->obj_at_put(i, ph());
|
|
587 }
|
|
588 } else {
|
|
589 // Get memory managers for a given memory pool
|
|
590 for (int i = 0; i < num_mgrs; i++) {
|
|
591 MemoryManager* mgr = pool->get_memory_manager(i);
|
|
592 instanceOop p = mgr->get_memory_manager_instance(CHECK_NULL);
|
|
593 instanceHandle ph(THREAD, p);
|
|
594 mgrArray->obj_at_put(i, ph());
|
|
595 }
|
|
596 }
|
|
597 return (jobjectArray) JNIHandles::make_local(env, mgrArray());
|
|
598 JVM_END
|
|
599
|
|
600
|
|
601 // Returns a java/lang/management/MemoryUsage object containing the memory usage
|
|
602 // of a given memory pool.
|
|
603 JVM_ENTRY(jobject, jmm_GetMemoryPoolUsage(JNIEnv* env, jobject obj))
|
|
604 ResourceMark rm(THREAD);
|
|
605
|
|
606 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
|
|
607 if (pool != NULL) {
|
|
608 MemoryUsage usage = pool->get_memory_usage();
|
|
609 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
|
|
610 return JNIHandles::make_local(env, h());
|
|
611 } else {
|
|
612 return NULL;
|
|
613 }
|
|
614 JVM_END
|
|
615
|
|
616 // Returns a java/lang/management/MemoryUsage object containing the memory usage
|
|
617 // of a given memory pool.
|
|
618 JVM_ENTRY(jobject, jmm_GetPeakMemoryPoolUsage(JNIEnv* env, jobject obj))
|
|
619 ResourceMark rm(THREAD);
|
|
620
|
|
621 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
|
|
622 if (pool != NULL) {
|
|
623 MemoryUsage usage = pool->get_peak_memory_usage();
|
|
624 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
|
|
625 return JNIHandles::make_local(env, h());
|
|
626 } else {
|
|
627 return NULL;
|
|
628 }
|
|
629 JVM_END
|
|
630
|
|
631 // Returns a java/lang/management/MemoryUsage object containing the memory usage
|
|
632 // of a given memory pool after most recent GC.
|
|
633 JVM_ENTRY(jobject, jmm_GetPoolCollectionUsage(JNIEnv* env, jobject obj))
|
|
634 ResourceMark rm(THREAD);
|
|
635
|
|
636 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
|
|
637 if (pool != NULL && pool->is_collected_pool()) {
|
|
638 MemoryUsage usage = pool->get_last_collection_usage();
|
|
639 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
|
|
640 return JNIHandles::make_local(env, h());
|
|
641 } else {
|
|
642 return NULL;
|
|
643 }
|
|
644 JVM_END
|
|
645
|
|
646 // Sets the memory pool sensor for a threshold type
|
|
647 JVM_ENTRY(void, jmm_SetPoolSensor(JNIEnv* env, jobject obj, jmmThresholdType type, jobject sensorObj))
|
|
648 if (obj == NULL || sensorObj == NULL) {
|
|
649 THROW(vmSymbols::java_lang_NullPointerException());
|
|
650 }
|
|
651
|
|
652 klassOop sensor_klass = Management::sun_management_Sensor_klass(CHECK);
|
|
653 oop s = JNIHandles::resolve(sensorObj);
|
|
654 assert(s->is_instance(), "Sensor should be an instanceOop");
|
|
655 instanceHandle sensor_h(THREAD, (instanceOop) s);
|
|
656 if (!sensor_h->is_a(sensor_klass)) {
|
|
657 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
|
658 "Sensor is not an instance of sun.management.Sensor class");
|
|
659 }
|
|
660
|
|
661 MemoryPool* mpool = get_memory_pool_from_jobject(obj, CHECK);
|
|
662 assert(mpool != NULL, "MemoryPool should exist");
|
|
663
|
|
664 switch (type) {
|
|
665 case JMM_USAGE_THRESHOLD_HIGH:
|
|
666 case JMM_USAGE_THRESHOLD_LOW:
|
|
667 // have only one sensor for threshold high and low
|
|
668 mpool->set_usage_sensor_obj(sensor_h);
|
|
669 break;
|
|
670 case JMM_COLLECTION_USAGE_THRESHOLD_HIGH:
|
|
671 case JMM_COLLECTION_USAGE_THRESHOLD_LOW:
|
|
672 // have only one sensor for threshold high and low
|
|
673 mpool->set_gc_usage_sensor_obj(sensor_h);
|
|
674 break;
|
|
675 default:
|
|
676 assert(false, "Unrecognized type");
|
|
677 }
|
|
678
|
|
679 JVM_END
|
|
680
|
|
681
|
|
682 // Sets the threshold of a given memory pool.
|
|
683 // Returns the previous threshold.
|
|
684 //
|
|
685 // Input parameters:
|
|
686 // pool - the MemoryPoolMXBean object
|
|
687 // type - threshold type
|
|
688 // threshold - the new threshold (must not be negative)
|
|
689 //
|
|
690 JVM_ENTRY(jlong, jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType type, jlong threshold))
|
|
691 if (threshold < 0) {
|
|
692 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
693 "Invalid threshold value",
|
|
694 -1);
|
|
695 }
|
|
696
|
|
697 if (threshold > max_intx) {
|
|
698 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
699 "Invalid threshold value > max value of size_t",
|
|
700 -1);
|
|
701 }
|
|
702
|
|
703 MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_(0L));
|
|
704 assert(pool != NULL, "MemoryPool should exist");
|
|
705
|
|
706 jlong prev = 0;
|
|
707 switch (type) {
|
|
708 case JMM_USAGE_THRESHOLD_HIGH:
|
|
709 if (!pool->usage_threshold()->is_high_threshold_supported()) {
|
|
710 return -1;
|
|
711 }
|
|
712 prev = pool->usage_threshold()->set_high_threshold((size_t) threshold);
|
|
713 break;
|
|
714
|
|
715 case JMM_USAGE_THRESHOLD_LOW:
|
|
716 if (!pool->usage_threshold()->is_low_threshold_supported()) {
|
|
717 return -1;
|
|
718 }
|
|
719 prev = pool->usage_threshold()->set_low_threshold((size_t) threshold);
|
|
720 break;
|
|
721
|
|
722 case JMM_COLLECTION_USAGE_THRESHOLD_HIGH:
|
|
723 if (!pool->gc_usage_threshold()->is_high_threshold_supported()) {
|
|
724 return -1;
|
|
725 }
|
|
726 // return and the new threshold is effective for the next GC
|
|
727 return pool->gc_usage_threshold()->set_high_threshold((size_t) threshold);
|
|
728
|
|
729 case JMM_COLLECTION_USAGE_THRESHOLD_LOW:
|
|
730 if (!pool->gc_usage_threshold()->is_low_threshold_supported()) {
|
|
731 return -1;
|
|
732 }
|
|
733 // return and the new threshold is effective for the next GC
|
|
734 return pool->gc_usage_threshold()->set_low_threshold((size_t) threshold);
|
|
735
|
|
736 default:
|
|
737 assert(false, "Unrecognized type");
|
|
738 return -1;
|
|
739 }
|
|
740
|
|
741 // When the threshold is changed, reevaluate if the low memory
|
|
742 // detection is enabled.
|
|
743 if (prev != threshold) {
|
|
744 LowMemoryDetector::recompute_enabled_for_collected_pools();
|
|
745 LowMemoryDetector::detect_low_memory(pool);
|
|
746 }
|
|
747 return prev;
|
|
748 JVM_END
|
|
749
|
|
750 // Returns a java/lang/management/MemoryUsage object representing
|
|
751 // the memory usage for the heap or non-heap memory.
|
|
752 JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
|
|
753 ResourceMark rm(THREAD);
|
|
754
|
|
755 // Calculate the memory usage
|
|
756 size_t total_init = 0;
|
|
757 size_t total_used = 0;
|
|
758 size_t total_committed = 0;
|
|
759 size_t total_max = 0;
|
|
760 bool has_undefined_init_size = false;
|
|
761 bool has_undefined_max_size = false;
|
|
762
|
|
763 for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
|
|
764 MemoryPool* pool = MemoryService::get_memory_pool(i);
|
|
765 if ((heap && pool->is_heap()) || (!heap && pool->is_non_heap())) {
|
|
766 MemoryUsage u = pool->get_memory_usage();
|
|
767 total_used += u.used();
|
|
768 total_committed += u.committed();
|
|
769
|
|
770 // if any one of the memory pool has undefined init_size or max_size,
|
|
771 // set it to -1
|
|
772 if (u.init_size() == (size_t)-1) {
|
|
773 has_undefined_init_size = true;
|
|
774 }
|
|
775 if (!has_undefined_init_size) {
|
|
776 total_init += u.init_size();
|
|
777 }
|
|
778
|
|
779 if (u.max_size() == (size_t)-1) {
|
|
780 has_undefined_max_size = true;
|
|
781 }
|
|
782 if (!has_undefined_max_size) {
|
|
783 total_max += u.max_size();
|
|
784 }
|
|
785 }
|
|
786 }
|
|
787
|
|
788 // In our current implementation, all pools should have
|
|
789 // defined init and max size
|
|
790 assert(!has_undefined_init_size, "Undefined init size");
|
|
791 assert(!has_undefined_max_size, "Undefined max size");
|
|
792
|
|
793 MemoryUsage usage((heap ? Arguments::initial_heap_size() : total_init),
|
|
794 total_used,
|
|
795 total_committed,
|
|
796 (heap ? Universe::heap()->max_capacity() : total_max));
|
|
797
|
|
798 Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
|
|
799 return JNIHandles::make_local(env, obj());
|
|
800 JVM_END
|
|
801
|
|
802 // Returns the boolean value of a given attribute.
|
|
803 JVM_LEAF(jboolean, jmm_GetBoolAttribute(JNIEnv *env, jmmBoolAttribute att))
|
|
804 switch (att) {
|
|
805 case JMM_VERBOSE_GC:
|
|
806 return MemoryService::get_verbose();
|
|
807 case JMM_VERBOSE_CLASS:
|
|
808 return ClassLoadingService::get_verbose();
|
|
809 case JMM_THREAD_CONTENTION_MONITORING:
|
|
810 return ThreadService::is_thread_monitoring_contention();
|
|
811 case JMM_THREAD_CPU_TIME:
|
|
812 return ThreadService::is_thread_cpu_time_enabled();
|
|
813 default:
|
|
814 assert(0, "Unrecognized attribute");
|
|
815 return false;
|
|
816 }
|
|
817 JVM_END
|
|
818
|
|
819 // Sets the given boolean attribute and returns the previous value.
|
|
820 JVM_ENTRY(jboolean, jmm_SetBoolAttribute(JNIEnv *env, jmmBoolAttribute att, jboolean flag))
|
|
821 switch (att) {
|
|
822 case JMM_VERBOSE_GC:
|
|
823 return MemoryService::set_verbose(flag != 0);
|
|
824 case JMM_VERBOSE_CLASS:
|
|
825 return ClassLoadingService::set_verbose(flag != 0);
|
|
826 case JMM_THREAD_CONTENTION_MONITORING:
|
|
827 return ThreadService::set_thread_monitoring_contention(flag != 0);
|
|
828 case JMM_THREAD_CPU_TIME:
|
|
829 return ThreadService::set_thread_cpu_time_enabled(flag != 0);
|
|
830 default:
|
|
831 assert(0, "Unrecognized attribute");
|
|
832 return false;
|
|
833 }
|
|
834 JVM_END
|
|
835
|
|
836
|
|
837 static jlong get_gc_attribute(GCMemoryManager* mgr, jmmLongAttribute att) {
|
|
838 switch (att) {
|
|
839 case JMM_GC_TIME_MS:
|
|
840 return mgr->gc_time_ms();
|
|
841
|
|
842 case JMM_GC_COUNT:
|
|
843 return mgr->gc_count();
|
|
844
|
|
845 case JMM_GC_EXT_ATTRIBUTE_INFO_SIZE:
|
|
846 // current implementation only has 1 ext attribute
|
|
847 return 1;
|
|
848
|
|
849 default:
|
|
850 assert(0, "Unrecognized GC attribute");
|
|
851 return -1;
|
|
852 }
|
|
853 }
|
|
854
|
|
855 class VmThreadCountClosure: public ThreadClosure {
|
|
856 private:
|
|
857 int _count;
|
|
858 public:
|
|
859 VmThreadCountClosure() : _count(0) {};
|
|
860 void do_thread(Thread* thread);
|
|
861 int count() { return _count; }
|
|
862 };
|
|
863
|
|
864 void VmThreadCountClosure::do_thread(Thread* thread) {
|
|
865 // exclude externally visible JavaThreads
|
|
866 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
|
|
867 return;
|
|
868 }
|
|
869
|
|
870 _count++;
|
|
871 }
|
|
872
|
|
873 static jint get_vm_thread_count() {
|
|
874 VmThreadCountClosure vmtcc;
|
|
875 {
|
|
876 MutexLockerEx ml(Threads_lock);
|
|
877 Threads::threads_do(&vmtcc);
|
|
878 }
|
|
879
|
|
880 return vmtcc.count();
|
|
881 }
|
|
882
|
|
883 static jint get_num_flags() {
|
|
884 // last flag entry is always NULL, so subtract 1
|
|
885 int nFlags = (int) Flag::numFlags - 1;
|
|
886 int count = 0;
|
|
887 for (int i = 0; i < nFlags; i++) {
|
|
888 Flag* flag = &Flag::flags[i];
|
|
889 // Exclude the diagnostic flags
|
|
890 if (flag->is_unlocked() || flag->is_unlocker()) {
|
|
891 count++;
|
|
892 }
|
|
893 }
|
|
894 return count;
|
|
895 }
|
|
896
|
|
897 static jlong get_long_attribute(jmmLongAttribute att) {
|
|
898 switch (att) {
|
|
899 case JMM_CLASS_LOADED_COUNT:
|
|
900 return ClassLoadingService::loaded_class_count();
|
|
901
|
|
902 case JMM_CLASS_UNLOADED_COUNT:
|
|
903 return ClassLoadingService::unloaded_class_count();
|
|
904
|
|
905 case JMM_THREAD_TOTAL_COUNT:
|
|
906 return ThreadService::get_total_thread_count();
|
|
907
|
|
908 case JMM_THREAD_LIVE_COUNT:
|
|
909 return ThreadService::get_live_thread_count();
|
|
910
|
|
911 case JMM_THREAD_PEAK_COUNT:
|
|
912 return ThreadService::get_peak_thread_count();
|
|
913
|
|
914 case JMM_THREAD_DAEMON_COUNT:
|
|
915 return ThreadService::get_daemon_thread_count();
|
|
916
|
|
917 case JMM_JVM_INIT_DONE_TIME_MS:
|
|
918 return Management::vm_init_done_time();
|
|
919
|
|
920 case JMM_COMPILE_TOTAL_TIME_MS:
|
|
921 return Management::ticks_to_ms(CompileBroker::total_compilation_ticks());
|
|
922
|
|
923 case JMM_OS_PROCESS_ID:
|
|
924 return os::current_process_id();
|
|
925
|
|
926 // Hotspot-specific counters
|
|
927 case JMM_CLASS_LOADED_BYTES:
|
|
928 return ClassLoadingService::loaded_class_bytes();
|
|
929
|
|
930 case JMM_CLASS_UNLOADED_BYTES:
|
|
931 return ClassLoadingService::unloaded_class_bytes();
|
|
932
|
|
933 case JMM_SHARED_CLASS_LOADED_COUNT:
|
|
934 return ClassLoadingService::loaded_shared_class_count();
|
|
935
|
|
936 case JMM_SHARED_CLASS_UNLOADED_COUNT:
|
|
937 return ClassLoadingService::unloaded_shared_class_count();
|
|
938
|
|
939
|
|
940 case JMM_SHARED_CLASS_LOADED_BYTES:
|
|
941 return ClassLoadingService::loaded_shared_class_bytes();
|
|
942
|
|
943 case JMM_SHARED_CLASS_UNLOADED_BYTES:
|
|
944 return ClassLoadingService::unloaded_shared_class_bytes();
|
|
945
|
|
946 case JMM_TOTAL_CLASSLOAD_TIME_MS:
|
|
947 return ClassLoader::classloader_time_ms();
|
|
948
|
|
949 case JMM_VM_GLOBAL_COUNT:
|
|
950 return get_num_flags();
|
|
951
|
|
952 case JMM_SAFEPOINT_COUNT:
|
|
953 return RuntimeService::safepoint_count();
|
|
954
|
|
955 case JMM_TOTAL_SAFEPOINTSYNC_TIME_MS:
|
|
956 return RuntimeService::safepoint_sync_time_ms();
|
|
957
|
|
958 case JMM_TOTAL_STOPPED_TIME_MS:
|
|
959 return RuntimeService::safepoint_time_ms();
|
|
960
|
|
961 case JMM_TOTAL_APP_TIME_MS:
|
|
962 return RuntimeService::application_time_ms();
|
|
963
|
|
964 case JMM_VM_THREAD_COUNT:
|
|
965 return get_vm_thread_count();
|
|
966
|
|
967 case JMM_CLASS_INIT_TOTAL_COUNT:
|
|
968 return ClassLoader::class_init_count();
|
|
969
|
|
970 case JMM_CLASS_INIT_TOTAL_TIME_MS:
|
|
971 return ClassLoader::class_init_time_ms();
|
|
972
|
|
973 case JMM_CLASS_VERIFY_TOTAL_TIME_MS:
|
|
974 return ClassLoader::class_verify_time_ms();
|
|
975
|
|
976 case JMM_METHOD_DATA_SIZE_BYTES:
|
|
977 return ClassLoadingService::class_method_data_size();
|
|
978
|
|
979 case JMM_OS_MEM_TOTAL_PHYSICAL_BYTES:
|
|
980 return os::physical_memory();
|
|
981
|
|
982 default:
|
|
983 return -1;
|
|
984 }
|
|
985 }
|
|
986
|
|
987
|
|
988 // Returns the long value of a given attribute.
|
|
989 JVM_ENTRY(jlong, jmm_GetLongAttribute(JNIEnv *env, jobject obj, jmmLongAttribute att))
|
|
990 if (obj == NULL) {
|
|
991 return get_long_attribute(att);
|
|
992 } else {
|
|
993 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_(0L));
|
|
994 if (mgr != NULL) {
|
|
995 return get_gc_attribute(mgr, att);
|
|
996 }
|
|
997 }
|
|
998 return -1;
|
|
999 JVM_END
|
|
1000
|
|
1001 // Gets the value of all attributes specified in the given array
|
|
1002 // and sets the value in the result array.
|
|
1003 // Returns the number of attributes found.
|
|
1004 JVM_ENTRY(jint, jmm_GetLongAttributes(JNIEnv *env,
|
|
1005 jobject obj,
|
|
1006 jmmLongAttribute* atts,
|
|
1007 jint count,
|
|
1008 jlong* result))
|
|
1009
|
|
1010 int num_atts = 0;
|
|
1011 if (obj == NULL) {
|
|
1012 for (int i = 0; i < count; i++) {
|
|
1013 result[i] = get_long_attribute(atts[i]);
|
|
1014 if (result[i] != -1) {
|
|
1015 num_atts++;
|
|
1016 }
|
|
1017 }
|
|
1018 } else {
|
|
1019 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK_0);
|
|
1020 for (int i = 0; i < count; i++) {
|
|
1021 result[i] = get_gc_attribute(mgr, atts[i]);
|
|
1022 if (result[i] != -1) {
|
|
1023 num_atts++;
|
|
1024 }
|
|
1025 }
|
|
1026 }
|
|
1027 return num_atts;
|
|
1028 JVM_END
|
|
1029
|
|
1030 // Helper function to do thread dump for a specific list of threads
|
|
1031 static void do_thread_dump(ThreadDumpResult* dump_result,
|
|
1032 typeArrayHandle ids_ah, // array of thread ID (long[])
|
|
1033 int num_threads,
|
|
1034 int max_depth,
|
|
1035 bool with_locked_monitors,
|
|
1036 bool with_locked_synchronizers,
|
|
1037 TRAPS) {
|
|
1038
|
|
1039 // First get an array of threadObj handles.
|
|
1040 // A JavaThread may terminate before we get the stack trace.
|
|
1041 GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);
|
|
1042 {
|
|
1043 MutexLockerEx ml(Threads_lock);
|
|
1044 for (int i = 0; i < num_threads; i++) {
|
|
1045 jlong tid = ids_ah->long_at(i);
|
|
1046 JavaThread* jt = find_java_thread_from_id(tid);
|
|
1047 oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL);
|
|
1048 instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj);
|
|
1049 thread_handle_array->append(threadObj_h);
|
|
1050 }
|
|
1051 }
|
|
1052
|
|
1053 // Obtain thread dumps and thread snapshot information
|
|
1054 VM_ThreadDump op(dump_result,
|
|
1055 thread_handle_array,
|
|
1056 num_threads,
|
|
1057 max_depth, /* stack depth */
|
|
1058 with_locked_monitors,
|
|
1059 with_locked_synchronizers);
|
|
1060 VMThread::execute(&op);
|
|
1061 }
|
|
1062
|
|
1063 // Gets an array of ThreadInfo objects. Each element is the ThreadInfo
|
|
1064 // for the thread ID specified in the corresponding entry in
|
|
1065 // the given array of thread IDs; or NULL if the thread does not exist
|
|
1066 // or has terminated.
|
|
1067 //
|
|
1068 // Input parameters:
|
|
1069 // ids - array of thread IDs
|
|
1070 // maxDepth - the maximum depth of stack traces to be dumped:
|
|
1071 // maxDepth == -1 requests to dump entire stack trace.
|
|
1072 // maxDepth == 0 requests no stack trace.
|
|
1073 // infoArray - array of ThreadInfo objects
|
|
1074 //
|
|
1075 JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray))
|
|
1076 // Check if threads is null
|
|
1077 if (ids == NULL || infoArray == NULL) {
|
|
1078 THROW_(vmSymbols::java_lang_NullPointerException(), -1);
|
|
1079 }
|
|
1080
|
|
1081 if (maxDepth < -1) {
|
|
1082 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1083 "Invalid maxDepth", -1);
|
|
1084 }
|
|
1085
|
|
1086 ResourceMark rm(THREAD);
|
|
1087 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
|
|
1088 typeArrayHandle ids_ah(THREAD, ta);
|
|
1089
|
|
1090 oop infoArray_obj = JNIHandles::resolve_non_null(infoArray);
|
|
1091 objArrayOop oa = objArrayOop(infoArray_obj);
|
|
1092 objArrayHandle infoArray_h(THREAD, oa);
|
|
1093
|
|
1094 // validate the thread id array
|
|
1095 validate_thread_id_array(ids_ah, CHECK_0);
|
|
1096
|
|
1097 // validate the ThreadInfo[] parameters
|
|
1098 validate_thread_info_array(infoArray_h, CHECK_0);
|
|
1099
|
|
1100 // infoArray must be of the same length as the given array of thread IDs
|
|
1101 int num_threads = ids_ah->length();
|
|
1102 if (num_threads != infoArray_h->length()) {
|
|
1103 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1104 "The length of the given ThreadInfo array does not match the length of the given array of thread IDs", -1);
|
|
1105 }
|
|
1106
|
|
1107 if (JDK_Version::is_gte_jdk16x_version()) {
|
|
1108 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
|
|
1109 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_0);
|
|
1110 }
|
|
1111
|
|
1112 // Must use ThreadDumpResult to store the ThreadSnapshot.
|
|
1113 // GC may occur after the thread snapshots are taken but before
|
|
1114 // this function returns. The threadObj and other oops kept
|
|
1115 // in the ThreadSnapshot are marked and adjusted during GC.
|
|
1116 ThreadDumpResult dump_result(num_threads);
|
|
1117
|
|
1118 if (maxDepth == 0) {
|
|
1119 // no stack trace dumped - do not need to stop the world
|
|
1120 {
|
|
1121 MutexLockerEx ml(Threads_lock);
|
|
1122 for (int i = 0; i < num_threads; i++) {
|
|
1123 jlong tid = ids_ah->long_at(i);
|
|
1124 JavaThread* jt = find_java_thread_from_id(tid);
|
|
1125 ThreadSnapshot* ts;
|
|
1126 if (jt == NULL) {
|
|
1127 // if the thread does not exist or now it is terminated,
|
|
1128 // create dummy snapshot
|
|
1129 ts = new ThreadSnapshot();
|
|
1130 } else {
|
|
1131 ts = new ThreadSnapshot(jt);
|
|
1132 }
|
|
1133 dump_result.add_thread_snapshot(ts);
|
|
1134 }
|
|
1135 }
|
|
1136 } else {
|
|
1137 // obtain thread dump with the specific list of threads with stack trace
|
|
1138
|
|
1139 do_thread_dump(&dump_result,
|
|
1140 ids_ah,
|
|
1141 num_threads,
|
|
1142 maxDepth,
|
|
1143 false, /* no locked monitor */
|
|
1144 false, /* no locked synchronizers */
|
|
1145 CHECK_0);
|
|
1146 }
|
|
1147
|
|
1148 int num_snapshots = dump_result.num_snapshots();
|
|
1149 assert(num_snapshots == num_threads, "Must match the number of thread snapshots");
|
|
1150 int index = 0;
|
|
1151 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) {
|
|
1152 // For each thread, create an java/lang/management/ThreadInfo object
|
|
1153 // and fill with the thread information
|
|
1154
|
|
1155 if (ts->threadObj() == NULL) {
|
|
1156 // if the thread does not exist or now it is terminated, set threadinfo to NULL
|
|
1157 infoArray_h->obj_at_put(index, NULL);
|
|
1158 continue;
|
|
1159 }
|
|
1160
|
|
1161 // Create java.lang.management.ThreadInfo object
|
|
1162 instanceOop info_obj = Management::create_thread_info_instance(ts, CHECK_0);
|
|
1163 infoArray_h->obj_at_put(index, info_obj);
|
|
1164 }
|
|
1165 return 0;
|
|
1166 JVM_END
|
|
1167
|
|
1168 // Dump thread info for the specified threads.
|
|
1169 // It returns an array of ThreadInfo objects. Each element is the ThreadInfo
|
|
1170 // for the thread ID specified in the corresponding entry in
|
|
1171 // the given array of thread IDs; or NULL if the thread does not exist
|
|
1172 // or has terminated.
|
|
1173 //
|
|
1174 // Input parameter:
|
|
1175 // ids - array of thread IDs; NULL indicates all live threads
|
|
1176 // locked_monitors - if true, dump locked object monitors
|
|
1177 // locked_synchronizers - if true, dump locked JSR-166 synchronizers
|
|
1178 //
|
|
1179 JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboolean locked_monitors, jboolean locked_synchronizers))
|
|
1180 ResourceMark rm(THREAD);
|
|
1181
|
|
1182 if (JDK_Version::is_gte_jdk16x_version()) {
|
|
1183 // make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
|
|
1184 java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_NULL);
|
|
1185 }
|
|
1186
|
|
1187 typeArrayOop ta = typeArrayOop(JNIHandles::resolve(thread_ids));
|
|
1188 int num_threads = (ta != NULL ? ta->length() : 0);
|
|
1189 typeArrayHandle ids_ah(THREAD, ta);
|
|
1190
|
|
1191 ThreadDumpResult dump_result(num_threads); // can safepoint
|
|
1192
|
|
1193 if (ids_ah() != NULL) {
|
|
1194
|
|
1195 // validate the thread id array
|
|
1196 validate_thread_id_array(ids_ah, CHECK_NULL);
|
|
1197
|
|
1198 // obtain thread dump of a specific list of threads
|
|
1199 do_thread_dump(&dump_result,
|
|
1200 ids_ah,
|
|
1201 num_threads,
|
|
1202 -1, /* entire stack */
|
|
1203 (locked_monitors ? true : false), /* with locked monitors */
|
|
1204 (locked_synchronizers ? true : false), /* with locked synchronizers */
|
|
1205 CHECK_NULL);
|
|
1206 } else {
|
|
1207 // obtain thread dump of all threads
|
|
1208 VM_ThreadDump op(&dump_result,
|
|
1209 -1, /* entire stack */
|
|
1210 (locked_monitors ? true : false), /* with locked monitors */
|
|
1211 (locked_synchronizers ? true : false) /* with locked synchronizers */);
|
|
1212 VMThread::execute(&op);
|
|
1213 }
|
|
1214
|
|
1215 int num_snapshots = dump_result.num_snapshots();
|
|
1216
|
|
1217 // create the result ThreadInfo[] object
|
|
1218 klassOop k = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
|
|
1219 instanceKlassHandle ik (THREAD, k);
|
|
1220 objArrayOop r = oopFactory::new_objArray(ik(), num_snapshots, CHECK_NULL);
|
|
1221 objArrayHandle result_h(THREAD, r);
|
|
1222
|
|
1223 int index = 0;
|
|
1224 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; ts = ts->next(), index++) {
|
|
1225 if (ts->threadObj() == NULL) {
|
|
1226 // if the thread does not exist or now it is terminated, set threadinfo to NULL
|
|
1227 result_h->obj_at_put(index, NULL);
|
|
1228 continue;
|
|
1229 }
|
|
1230
|
|
1231
|
|
1232
|
|
1233 ThreadStackTrace* stacktrace = ts->get_stack_trace();
|
|
1234 assert(stacktrace != NULL, "Must have a stack trace dumped");
|
|
1235
|
|
1236 // Create Object[] filled with locked monitors
|
|
1237 // Create int[] filled with the stack depth where a monitor was locked
|
|
1238 int num_frames = stacktrace->get_stack_depth();
|
|
1239 int num_locked_monitors = stacktrace->num_jni_locked_monitors();
|
|
1240
|
|
1241 // Count the total number of locked monitors
|
|
1242 for (int i = 0; i < num_frames; i++) {
|
|
1243 StackFrameInfo* frame = stacktrace->stack_frame_at(i);
|
|
1244 num_locked_monitors += frame->num_locked_monitors();
|
|
1245 }
|
|
1246
|
|
1247 objArrayHandle monitors_array;
|
|
1248 typeArrayHandle depths_array;
|
|
1249 objArrayHandle synchronizers_array;
|
|
1250
|
|
1251 if (locked_monitors) {
|
|
1252 // Constructs Object[] and int[] to contain the object monitor and the stack depth
|
|
1253 // where the thread locked it
|
|
1254 objArrayOop array = oopFactory::new_system_objArray(num_locked_monitors, CHECK_NULL);
|
|
1255 objArrayHandle mh(THREAD, array);
|
|
1256 monitors_array = mh;
|
|
1257
|
|
1258 typeArrayOop tarray = oopFactory::new_typeArray(T_INT, num_locked_monitors, CHECK_NULL);
|
|
1259 typeArrayHandle dh(THREAD, tarray);
|
|
1260 depths_array = dh;
|
|
1261
|
|
1262 int count = 0;
|
|
1263 int j = 0;
|
|
1264 for (int depth = 0; depth < num_frames; depth++) {
|
|
1265 StackFrameInfo* frame = stacktrace->stack_frame_at(depth);
|
|
1266 int len = frame->num_locked_monitors();
|
|
1267 GrowableArray<oop>* locked_monitors = frame->locked_monitors();
|
|
1268 for (j = 0; j < len; j++) {
|
|
1269 oop monitor = locked_monitors->at(j);
|
|
1270 assert(monitor != NULL && monitor->is_instance(), "must be a Java object");
|
|
1271 monitors_array->obj_at_put(count, monitor);
|
|
1272 depths_array->int_at_put(count, depth);
|
|
1273 count++;
|
|
1274 }
|
|
1275 }
|
|
1276
|
|
1277 GrowableArray<oop>* jni_locked_monitors = stacktrace->jni_locked_monitors();
|
|
1278 for (j = 0; j < jni_locked_monitors->length(); j++) {
|
|
1279 oop object = jni_locked_monitors->at(j);
|
|
1280 assert(object != NULL && object->is_instance(), "must be a Java object");
|
|
1281 monitors_array->obj_at_put(count, object);
|
|
1282 // Monitor locked via JNI MonitorEnter call doesn't have stack depth info
|
|
1283 depths_array->int_at_put(count, -1);
|
|
1284 count++;
|
|
1285 }
|
|
1286 assert(count == num_locked_monitors, "number of locked monitors doesn't match");
|
|
1287 }
|
|
1288
|
|
1289 if (locked_synchronizers) {
|
|
1290 // Create Object[] filled with locked JSR-166 synchronizers
|
|
1291 assert(ts->threadObj() != NULL, "Must be a valid JavaThread");
|
|
1292 ThreadConcurrentLocks* tcl = ts->get_concurrent_locks();
|
|
1293 GrowableArray<instanceOop>* locks = (tcl != NULL ? tcl->owned_locks() : NULL);
|
|
1294 int num_locked_synchronizers = (locks != NULL ? locks->length() : 0);
|
|
1295
|
|
1296 objArrayOop array = oopFactory::new_system_objArray(num_locked_synchronizers, CHECK_NULL);
|
|
1297 objArrayHandle sh(THREAD, array);
|
|
1298 synchronizers_array = sh;
|
|
1299
|
|
1300 for (int k = 0; k < num_locked_synchronizers; k++) {
|
|
1301 synchronizers_array->obj_at_put(k, locks->at(k));
|
|
1302 }
|
|
1303 }
|
|
1304
|
|
1305 // Create java.lang.management.ThreadInfo object
|
|
1306 instanceOop info_obj = Management::create_thread_info_instance(ts,
|
|
1307 monitors_array,
|
|
1308 depths_array,
|
|
1309 synchronizers_array,
|
|
1310 CHECK_NULL);
|
|
1311 result_h->obj_at_put(index, info_obj);
|
|
1312 }
|
|
1313
|
|
1314 return (jobjectArray) JNIHandles::make_local(env, result_h());
|
|
1315 JVM_END
|
|
1316
|
|
1317 // Returns an array of Class objects.
|
|
1318 JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env))
|
|
1319 ResourceMark rm(THREAD);
|
|
1320
|
|
1321 LoadedClassesEnumerator lce(THREAD); // Pass current Thread as parameter
|
|
1322
|
|
1323 int num_classes = lce.num_loaded_classes();
|
|
1324 objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), num_classes, CHECK_0);
|
|
1325 objArrayHandle classes_ah(THREAD, r);
|
|
1326
|
|
1327 for (int i = 0; i < num_classes; i++) {
|
|
1328 KlassHandle kh = lce.get_klass(i);
|
|
1329 oop mirror = Klass::cast(kh())->java_mirror();
|
|
1330 classes_ah->obj_at_put(i, mirror);
|
|
1331 }
|
|
1332
|
|
1333 return (jobjectArray) JNIHandles::make_local(env, classes_ah());
|
|
1334 JVM_END
|
|
1335
|
|
1336 // Reset statistic. Return true if the requested statistic is reset.
|
|
1337 // Otherwise, return false.
|
|
1338 //
|
|
1339 // Input parameters:
|
|
1340 // obj - specify which instance the statistic associated with to be reset
|
|
1341 // For PEAK_POOL_USAGE stat, obj is required to be a memory pool object.
|
|
1342 // For THREAD_CONTENTION_COUNT and TIME stat, obj is required to be a thread ID.
|
|
1343 // type - the type of statistic to be reset
|
|
1344 //
|
|
1345 JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType type))
|
|
1346 ResourceMark rm(THREAD);
|
|
1347
|
|
1348 switch (type) {
|
|
1349 case JMM_STAT_PEAK_THREAD_COUNT:
|
|
1350 ThreadService::reset_peak_thread_count();
|
|
1351 return true;
|
|
1352
|
|
1353 case JMM_STAT_THREAD_CONTENTION_COUNT:
|
|
1354 case JMM_STAT_THREAD_CONTENTION_TIME: {
|
|
1355 jlong tid = obj.j;
|
|
1356 if (tid < 0) {
|
|
1357 THROW_(vmSymbols::java_lang_IllegalArgumentException(), JNI_FALSE);
|
|
1358 }
|
|
1359
|
|
1360 // Look for the JavaThread of this given tid
|
|
1361 MutexLockerEx ml(Threads_lock);
|
|
1362 if (tid == 0) {
|
|
1363 // reset contention statistics for all threads if tid == 0
|
|
1364 for (JavaThread* java_thread = Threads::first(); java_thread != NULL; java_thread = java_thread->next()) {
|
|
1365 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
|
|
1366 ThreadService::reset_contention_count_stat(java_thread);
|
|
1367 } else {
|
|
1368 ThreadService::reset_contention_time_stat(java_thread);
|
|
1369 }
|
|
1370 }
|
|
1371 } else {
|
|
1372 // reset contention statistics for a given thread
|
|
1373 JavaThread* java_thread = find_java_thread_from_id(tid);
|
|
1374 if (java_thread == NULL) {
|
|
1375 return false;
|
|
1376 }
|
|
1377
|
|
1378 if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
|
|
1379 ThreadService::reset_contention_count_stat(java_thread);
|
|
1380 } else {
|
|
1381 ThreadService::reset_contention_time_stat(java_thread);
|
|
1382 }
|
|
1383 }
|
|
1384 return true;
|
|
1385 break;
|
|
1386 }
|
|
1387 case JMM_STAT_PEAK_POOL_USAGE: {
|
|
1388 jobject o = obj.l;
|
|
1389 if (o == NULL) {
|
|
1390 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
|
|
1391 }
|
|
1392
|
|
1393 oop pool_obj = JNIHandles::resolve(o);
|
|
1394 assert(pool_obj->is_instance(), "Should be an instanceOop");
|
|
1395 instanceHandle ph(THREAD, (instanceOop) pool_obj);
|
|
1396
|
|
1397 MemoryPool* pool = MemoryService::get_memory_pool(ph);
|
|
1398 if (pool != NULL) {
|
|
1399 pool->reset_peak_memory_usage();
|
|
1400 return true;
|
|
1401 }
|
|
1402 break;
|
|
1403 }
|
|
1404 case JMM_STAT_GC_STAT: {
|
|
1405 jobject o = obj.l;
|
|
1406 if (o == NULL) {
|
|
1407 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
|
|
1408 }
|
|
1409
|
|
1410 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(o, CHECK_0);
|
|
1411 if (mgr != NULL) {
|
|
1412 mgr->reset_gc_stat();
|
|
1413 return true;
|
|
1414 }
|
|
1415 break;
|
|
1416 }
|
|
1417 default:
|
|
1418 assert(0, "Unknown Statistic Type");
|
|
1419 }
|
|
1420 return false;
|
|
1421 JVM_END
|
|
1422
|
|
1423 // Returns the fast estimate of CPU time consumed by
|
|
1424 // a given thread (in nanoseconds).
|
|
1425 // If thread_id == 0, return CPU time for the current thread.
|
|
1426 JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id))
|
|
1427 if (!os::is_thread_cpu_time_supported()) {
|
|
1428 return -1;
|
|
1429 }
|
|
1430
|
|
1431 if (thread_id < 0) {
|
|
1432 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1433 "Invalid thread ID", -1);
|
|
1434 }
|
|
1435
|
|
1436 JavaThread* java_thread = NULL;
|
|
1437 if (thread_id == 0) {
|
|
1438 // current thread
|
|
1439 return os::current_thread_cpu_time();
|
|
1440 } else {
|
|
1441 MutexLockerEx ml(Threads_lock);
|
|
1442 java_thread = find_java_thread_from_id(thread_id);
|
|
1443 if (java_thread != NULL) {
|
|
1444 return os::thread_cpu_time((Thread*) java_thread);
|
|
1445 }
|
|
1446 }
|
|
1447 return -1;
|
|
1448 JVM_END
|
|
1449
|
|
1450 // Returns the CPU time consumed by a given thread (in nanoseconds).
|
|
1451 // If thread_id == 0, CPU time for the current thread is returned.
|
|
1452 // If user_sys_cpu_time = true, user level and system CPU time of
|
|
1453 // a given thread is returned; otherwise, only user level CPU time
|
|
1454 // is returned.
|
|
1455 JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time))
|
|
1456 if (!os::is_thread_cpu_time_supported()) {
|
|
1457 return -1;
|
|
1458 }
|
|
1459
|
|
1460 if (thread_id < 0) {
|
|
1461 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1462 "Invalid thread ID", -1);
|
|
1463 }
|
|
1464
|
|
1465 JavaThread* java_thread = NULL;
|
|
1466 if (thread_id == 0) {
|
|
1467 // current thread
|
|
1468 return os::current_thread_cpu_time(user_sys_cpu_time != 0);
|
|
1469 } else {
|
|
1470 MutexLockerEx ml(Threads_lock);
|
|
1471 java_thread = find_java_thread_from_id(thread_id);
|
|
1472 if (java_thread != NULL) {
|
|
1473 return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
|
|
1474 }
|
|
1475 }
|
|
1476 return -1;
|
|
1477 JVM_END
|
|
1478
|
|
1479 // Returns a String array of all VM global flag names
|
|
1480 JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
|
|
1481 // last flag entry is always NULL, so subtract 1
|
|
1482 int nFlags = (int) Flag::numFlags - 1;
|
|
1483 // allocate a temp array
|
|
1484 objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(),
|
|
1485 nFlags, CHECK_0);
|
|
1486 objArrayHandle flags_ah(THREAD, r);
|
|
1487 int num_entries = 0;
|
|
1488 for (int i = 0; i < nFlags; i++) {
|
|
1489 Flag* flag = &Flag::flags[i];
|
|
1490 // Exclude the diagnostic flags
|
|
1491 if (flag->is_unlocked() || flag->is_unlocker()) {
|
|
1492 Handle s = java_lang_String::create_from_str(flag->name, CHECK_0);
|
|
1493 flags_ah->obj_at_put(num_entries, s());
|
|
1494 num_entries++;
|
|
1495 }
|
|
1496 }
|
|
1497
|
|
1498 if (num_entries < nFlags) {
|
|
1499 // Return array of right length
|
|
1500 objArrayOop res = oopFactory::new_objArray(SystemDictionary::string_klass(), num_entries, CHECK_0);
|
|
1501 for(int i = 0; i < num_entries; i++) {
|
|
1502 res->obj_at_put(i, flags_ah->obj_at(i));
|
|
1503 }
|
|
1504 return (jobjectArray)JNIHandles::make_local(env, res);
|
|
1505 }
|
|
1506
|
|
1507 return (jobjectArray)JNIHandles::make_local(env, flags_ah());
|
|
1508 JVM_END
|
|
1509
|
|
1510 // utility function used by jmm_GetVMGlobals
|
|
1511 void add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag, TRAPS) {
|
|
1512 Handle flag_name;
|
|
1513 if (name() == NULL) {
|
|
1514 flag_name = java_lang_String::create_from_str(flag->name, CHECK);
|
|
1515 } else {
|
|
1516 flag_name = name;
|
|
1517 }
|
|
1518 global->name = (jstring)JNIHandles::make_local(env, flag_name());
|
|
1519 global->type = JMM_VMGLOBAL_TYPE_UNKNOWN;
|
|
1520
|
|
1521 if (flag->is_bool()) {
|
|
1522 global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE;
|
|
1523 global->type = JMM_VMGLOBAL_TYPE_JBOOLEAN;
|
|
1524 } else if (flag->is_intx()) {
|
|
1525 global->value.j = (jlong)flag->get_intx();
|
|
1526 global->type = JMM_VMGLOBAL_TYPE_JLONG;
|
|
1527 } else if (flag->is_uintx()) {
|
|
1528 global->value.j = (jlong)flag->get_uintx();
|
|
1529 global->type = JMM_VMGLOBAL_TYPE_JLONG;
|
|
1530 } else if (flag->is_ccstr()) {
|
|
1531 Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK);
|
|
1532 global->value.l = (jobject)JNIHandles::make_local(env, str());
|
|
1533 global->type = JMM_VMGLOBAL_TYPE_JSTRING;
|
|
1534 }
|
|
1535
|
|
1536 global->writeable = flag->is_writeable();
|
|
1537 global->external = flag->is_external();
|
|
1538 switch (flag->origin) {
|
|
1539 case DEFAULT:
|
|
1540 global->origin = JMM_VMGLOBAL_ORIGIN_DEFAULT;
|
|
1541 break;
|
|
1542 case COMMAND_LINE:
|
|
1543 global->origin = JMM_VMGLOBAL_ORIGIN_COMMAND_LINE;
|
|
1544 break;
|
|
1545 case ENVIRON_VAR:
|
|
1546 global->origin = JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR;
|
|
1547 break;
|
|
1548 case CONFIG_FILE:
|
|
1549 global->origin = JMM_VMGLOBAL_ORIGIN_CONFIG_FILE;
|
|
1550 break;
|
|
1551 case MANAGEMENT:
|
|
1552 global->origin = JMM_VMGLOBAL_ORIGIN_MANAGEMENT;
|
|
1553 break;
|
|
1554 case ERGONOMIC:
|
|
1555 global->origin = JMM_VMGLOBAL_ORIGIN_ERGONOMIC;
|
|
1556 break;
|
|
1557 default:
|
|
1558 global->origin = JMM_VMGLOBAL_ORIGIN_OTHER;
|
|
1559 }
|
|
1560 }
|
|
1561
|
|
1562 // Fill globals array of count length with jmmVMGlobal entries
|
|
1563 // specified by names. If names == NULL, fill globals array
|
|
1564 // with all Flags. Return value is number of entries
|
|
1565 // created in globals.
|
|
1566 // If a Flag with a given name in an array element does not
|
|
1567 // exist, globals[i].name will be set to NULL.
|
|
1568 JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
|
|
1569 jobjectArray names,
|
|
1570 jmmVMGlobal *globals,
|
|
1571 jint count))
|
|
1572
|
|
1573
|
|
1574 if (globals == NULL) {
|
|
1575 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
|
|
1576 }
|
|
1577
|
|
1578 ResourceMark rm(THREAD);
|
|
1579
|
|
1580 if (names != NULL) {
|
|
1581 // return the requested globals
|
|
1582 objArrayOop ta = objArrayOop(JNIHandles::resolve_non_null(names));
|
|
1583 objArrayHandle names_ah(THREAD, ta);
|
|
1584 // Make sure we have a String array
|
|
1585 klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass();
|
|
1586 if (element_klass != SystemDictionary::string_klass()) {
|
|
1587 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1588 "Array element type is not String class", 0);
|
|
1589 }
|
|
1590
|
|
1591 int names_length = names_ah->length();
|
|
1592 int num_entries = 0;
|
|
1593 for (int i = 0; i < names_length && i < count; i++) {
|
|
1594 oop s = names_ah->obj_at(i);
|
|
1595 if (s == NULL) {
|
|
1596 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
|
|
1597 }
|
|
1598
|
|
1599 Handle sh(THREAD, s);
|
|
1600 char* str = java_lang_String::as_utf8_string(s);
|
|
1601 Flag* flag = Flag::find_flag(str, strlen(str));
|
|
1602 if (flag != NULL) {
|
|
1603 add_global_entry(env, sh, &globals[i], flag, THREAD);
|
|
1604 num_entries++;
|
|
1605 } else {
|
|
1606 globals[i].name = NULL;
|
|
1607 }
|
|
1608 }
|
|
1609 return num_entries;
|
|
1610 } else {
|
|
1611 // return all globals if names == NULL
|
|
1612
|
|
1613 // last flag entry is always NULL, so subtract 1
|
|
1614 int nFlags = (int) Flag::numFlags - 1;
|
|
1615 Handle null_h;
|
|
1616 int num_entries = 0;
|
|
1617 for (int i = 0; i < nFlags && num_entries < count; i++) {
|
|
1618 Flag* flag = &Flag::flags[i];
|
|
1619 // Exclude the diagnostic flags
|
|
1620 if (flag->is_unlocked() || flag->is_unlocker()) {
|
|
1621 add_global_entry(env, null_h, &globals[num_entries], flag, THREAD);
|
|
1622 num_entries++;
|
|
1623 }
|
|
1624 }
|
|
1625 return num_entries;
|
|
1626 }
|
|
1627 JVM_END
|
|
1628
|
|
1629 JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value))
|
|
1630 ResourceMark rm(THREAD);
|
|
1631
|
|
1632 oop fn = JNIHandles::resolve_external_guard(flag_name);
|
|
1633 if (fn == NULL) {
|
|
1634 THROW_MSG(vmSymbols::java_lang_NullPointerException(),
|
|
1635 "The flag name cannot be null.");
|
|
1636 }
|
|
1637 char* name = java_lang_String::as_utf8_string(fn);
|
|
1638 Flag* flag = Flag::find_flag(name, strlen(name));
|
|
1639 if (flag == NULL) {
|
|
1640 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1641 "Flag does not exist.");
|
|
1642 }
|
|
1643 if (!flag->is_writeable()) {
|
|
1644 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1645 "This flag is not writeable.");
|
|
1646 }
|
|
1647
|
|
1648 bool succeed;
|
|
1649 if (flag->is_bool()) {
|
|
1650 bool bvalue = (new_value.z == JNI_TRUE ? true : false);
|
|
1651 succeed = CommandLineFlags::boolAtPut(name, &bvalue, MANAGEMENT);
|
|
1652 } else if (flag->is_intx()) {
|
|
1653 intx ivalue = new_value.j;
|
|
1654 succeed = CommandLineFlags::intxAtPut(name, &ivalue, MANAGEMENT);
|
|
1655 } else if (flag->is_uintx()) {
|
|
1656 uintx uvalue = new_value.j;
|
|
1657 succeed = CommandLineFlags::uintxAtPut(name, &uvalue, MANAGEMENT);
|
|
1658 } else if (flag->is_ccstr()) {
|
|
1659 oop str = JNIHandles::resolve_external_guard(new_value.l);
|
|
1660 if (str == NULL) {
|
|
1661 THROW(vmSymbols::java_lang_NullPointerException());
|
|
1662 }
|
|
1663 ccstr svalue = java_lang_String::as_utf8_string(str);
|
|
1664 succeed = CommandLineFlags::ccstrAtPut(name, &svalue, MANAGEMENT);
|
|
1665 }
|
|
1666 assert(succeed, "Setting flag should succeed");
|
|
1667 JVM_END
|
|
1668
|
|
1669 class ThreadTimesClosure: public ThreadClosure {
|
|
1670 private:
|
|
1671 objArrayOop _names;
|
|
1672 typeArrayOop _times;
|
|
1673 int _names_len;
|
|
1674 int _times_len;
|
|
1675 int _count;
|
|
1676
|
|
1677 public:
|
|
1678 ThreadTimesClosure(objArrayOop names, typeArrayOop times);
|
|
1679 virtual void do_thread(Thread* thread);
|
|
1680 int count() { return _count; }
|
|
1681 };
|
|
1682
|
|
1683 ThreadTimesClosure::ThreadTimesClosure(objArrayOop names,
|
|
1684 typeArrayOop times) {
|
|
1685 assert(names != NULL, "names was NULL");
|
|
1686 assert(times != NULL, "times was NULL");
|
|
1687 _names = names;
|
|
1688 _names_len = names->length();
|
|
1689 _times = times;
|
|
1690 _times_len = times->length();
|
|
1691 _count = 0;
|
|
1692 }
|
|
1693
|
|
1694 void ThreadTimesClosure::do_thread(Thread* thread) {
|
|
1695 Handle s;
|
|
1696 assert(thread != NULL, "thread was NULL");
|
|
1697
|
|
1698 // exclude externally visible JavaThreads
|
|
1699 if (thread->is_Java_thread() && !thread->is_hidden_from_external_view()) {
|
|
1700 return;
|
|
1701 }
|
|
1702
|
|
1703 if (_count >= _names_len || _count >= _times_len) {
|
|
1704 // skip if the result array is not big enough
|
|
1705 return;
|
|
1706 }
|
|
1707
|
|
1708 EXCEPTION_MARK;
|
|
1709
|
|
1710 assert(thread->name() != NULL, "All threads should have a name");
|
|
1711 s = java_lang_String::create_from_str(thread->name(), CHECK);
|
|
1712 _names->obj_at_put(_count, s());
|
|
1713
|
|
1714 _times->long_at_put(_count, os::is_thread_cpu_time_supported() ?
|
|
1715 os::thread_cpu_time(thread) : -1);
|
|
1716 _count++;
|
|
1717 }
|
|
1718
|
|
1719 // Fills names with VM internal thread names and times with the corresponding
|
|
1720 // CPU times. If names or times is NULL, a NullPointerException is thrown.
|
|
1721 // If the element type of names is not String, an IllegalArgumentException is
|
|
1722 // thrown.
|
|
1723 // If an array is not large enough to hold all the entries, only the entries
|
|
1724 // that fit will be returned. Return value is the number of VM internal
|
|
1725 // threads entries.
|
|
1726 JVM_ENTRY(jint, jmm_GetInternalThreadTimes(JNIEnv *env,
|
|
1727 jobjectArray names,
|
|
1728 jlongArray times))
|
|
1729 if (names == NULL || times == NULL) {
|
|
1730 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
|
|
1731 }
|
|
1732 objArrayOop na = objArrayOop(JNIHandles::resolve_non_null(names));
|
|
1733 objArrayHandle names_ah(THREAD, na);
|
|
1734
|
|
1735 // Make sure we have a String array
|
|
1736 klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass();
|
|
1737 if (element_klass != SystemDictionary::string_klass()) {
|
|
1738 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1739 "Array element type is not String class", 0);
|
|
1740 }
|
|
1741
|
|
1742 typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(times));
|
|
1743 typeArrayHandle times_ah(THREAD, ta);
|
|
1744
|
|
1745 ThreadTimesClosure ttc(names_ah(), times_ah());
|
|
1746 {
|
|
1747 MutexLockerEx ml(Threads_lock);
|
|
1748 Threads::threads_do(&ttc);
|
|
1749 }
|
|
1750
|
|
1751 return ttc.count();
|
|
1752 JVM_END
|
|
1753
|
|
1754 static Handle find_deadlocks(bool object_monitors_only, TRAPS) {
|
|
1755 ResourceMark rm(THREAD);
|
|
1756
|
|
1757 VM_FindDeadlocks op(!object_monitors_only /* also check concurrent locks? */);
|
|
1758 VMThread::execute(&op);
|
|
1759
|
|
1760 DeadlockCycle* deadlocks = op.result();
|
|
1761 if (deadlocks == NULL) {
|
|
1762 // no deadlock found and return
|
|
1763 return Handle();
|
|
1764 }
|
|
1765
|
|
1766 int num_threads = 0;
|
|
1767 DeadlockCycle* cycle;
|
|
1768 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) {
|
|
1769 num_threads += cycle->num_threads();
|
|
1770 }
|
|
1771
|
|
1772 objArrayOop r = oopFactory::new_objArray(SystemDictionary::thread_klass(), num_threads, CHECK_NH);
|
|
1773 objArrayHandle threads_ah(THREAD, r);
|
|
1774
|
|
1775 int index = 0;
|
|
1776 for (cycle = deadlocks; cycle != NULL; cycle = cycle->next()) {
|
|
1777 GrowableArray<JavaThread*>* deadlock_threads = cycle->threads();
|
|
1778 int len = deadlock_threads->length();
|
|
1779 for (int i = 0; i < len; i++) {
|
|
1780 threads_ah->obj_at_put(index, deadlock_threads->at(i)->threadObj());
|
|
1781 index++;
|
|
1782 }
|
|
1783 }
|
|
1784 return threads_ah;
|
|
1785 }
|
|
1786
|
|
1787 // Finds cycles of threads that are deadlocked involved in object monitors
|
|
1788 // and JSR-166 synchronizers.
|
|
1789 // Returns an array of Thread objects which are in deadlock, if any.
|
|
1790 // Otherwise, returns NULL.
|
|
1791 //
|
|
1792 // Input parameter:
|
|
1793 // object_monitors_only - if true, only check object monitors
|
|
1794 //
|
|
1795 JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only))
|
|
1796 Handle result = find_deadlocks(object_monitors_only != 0, CHECK_0);
|
|
1797 return (jobjectArray) JNIHandles::make_local(env, result());
|
|
1798 JVM_END
|
|
1799
|
|
1800 // Finds cycles of threads that are deadlocked on monitor locks
|
|
1801 // Returns an array of Thread objects which are in deadlock, if any.
|
|
1802 // Otherwise, returns NULL.
|
|
1803 JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env))
|
|
1804 Handle result = find_deadlocks(true, CHECK_0);
|
|
1805 return (jobjectArray) JNIHandles::make_local(env, result());
|
|
1806 JVM_END
|
|
1807
|
|
1808 // Gets the information about GC extension attributes including
|
|
1809 // the name of the attribute, its type, and a short description.
|
|
1810 //
|
|
1811 // Input parameters:
|
|
1812 // mgr - GC memory manager
|
|
1813 // info - caller allocated array of jmmExtAttributeInfo
|
|
1814 // count - number of elements of the info array
|
|
1815 //
|
|
1816 // Returns the number of GC extension attributes filled in the info array; or
|
|
1817 // -1 if info is not big enough
|
|
1818 //
|
|
1819 JVM_ENTRY(jint, jmm_GetGCExtAttributeInfo(JNIEnv *env, jobject mgr, jmmExtAttributeInfo* info, jint count))
|
|
1820 // All GC memory managers have 1 attribute (number of GC threads)
|
|
1821 if (count == 0) {
|
|
1822 return 0;
|
|
1823 }
|
|
1824
|
|
1825 if (info == NULL) {
|
|
1826 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
|
|
1827 }
|
|
1828
|
|
1829 info[0].name = "GcThreadCount";
|
|
1830 info[0].type = 'I';
|
|
1831 info[0].description = "Number of GC threads";
|
|
1832 return 1;
|
|
1833 JVM_END
|
|
1834
|
|
1835 // verify the given array is an array of java/lang/management/MemoryUsage objects
|
|
1836 // of a given length and return the objArrayOop
|
|
1837 static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRAPS) {
|
|
1838 if (array == NULL) {
|
|
1839 THROW_(vmSymbols::java_lang_NullPointerException(), 0);
|
|
1840 }
|
|
1841
|
|
1842 objArrayOop oa = objArrayOop(JNIHandles::resolve_non_null(array));
|
|
1843 objArrayHandle array_h(THREAD, oa);
|
|
1844
|
|
1845 // array must be of the given length
|
|
1846 if (length != array_h->length()) {
|
|
1847 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1848 "The length of the given MemoryUsage array does not match the number of memory pools.", 0);
|
|
1849 }
|
|
1850
|
|
1851 // check if the element of array is of type MemoryUsage class
|
|
1852 klassOop usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_0);
|
|
1853 klassOop element_klass = objArrayKlass::cast(array_h->klass())->element_klass();
|
|
1854 if (element_klass != usage_klass) {
|
|
1855 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
|
|
1856 "The element type is not MemoryUsage class", 0);
|
|
1857 }
|
|
1858
|
|
1859 return array_h();
|
|
1860 }
|
|
1861
|
|
1862 // Gets the statistics of the last GC of a given GC memory manager.
|
|
1863 // Input parameters:
|
|
1864 // obj - GarbageCollectorMXBean object
|
|
1865 // gc_stat - caller allocated jmmGCStat where:
|
|
1866 // a. before_gc_usage - array of MemoryUsage objects
|
|
1867 // b. after_gc_usage - array of MemoryUsage objects
|
|
1868 // c. gc_ext_attributes_values_size is set to the
|
|
1869 // gc_ext_attribute_values array allocated
|
|
1870 // d. gc_ext_attribute_values is a caller allocated array of jvalue.
|
|
1871 //
|
|
1872 // On return,
|
|
1873 // gc_index == 0 indicates no GC statistics available
|
|
1874 //
|
|
1875 // before_gc_usage and after_gc_usage - filled with per memory pool
|
|
1876 // before and after GC usage in the same order as the memory pools
|
|
1877 // returned by GetMemoryPools for a given GC memory manager.
|
|
1878 // num_gc_ext_attributes indicates the number of elements in
|
|
1879 // the gc_ext_attribute_values array is filled; or
|
|
1880 // -1 if the gc_ext_attributes_values array is not big enough
|
|
1881 //
|
|
1882 JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat))
|
|
1883 ResourceMark rm(THREAD);
|
|
1884
|
|
1885 if (gc_stat->gc_ext_attribute_values_size > 0 && gc_stat->gc_ext_attribute_values == NULL) {
|
|
1886 THROW(vmSymbols::java_lang_NullPointerException());
|
|
1887 }
|
|
1888
|
|
1889 // Get the GCMemoryManager
|
|
1890 GCMemoryManager* mgr = get_gc_memory_manager_from_jobject(obj, CHECK);
|
|
1891 if (mgr->last_gc_stat() == NULL) {
|
|
1892 gc_stat->gc_index = 0;
|
|
1893 return;
|
|
1894 }
|
|
1895
|
|
1896 // Make a copy of the last GC statistics
|
|
1897 // GC may occur while constructing the last GC information
|
|
1898 int num_pools = MemoryService::num_memory_pools();
|
|
1899 GCStatInfo* stat = new GCStatInfo(num_pools);
|
|
1900 stat->copy_stat(mgr->last_gc_stat());
|
|
1901
|
|
1902 gc_stat->gc_index = stat->gc_index();
|
|
1903 gc_stat->start_time = Management::ticks_to_ms(stat->start_time());
|
|
1904 gc_stat->end_time = Management::ticks_to_ms(stat->end_time());
|
|
1905
|
|
1906 // Current implementation does not have GC extension attributes
|
|
1907 gc_stat->num_gc_ext_attributes = 0;
|
|
1908
|
|
1909 // Fill the arrays of MemoryUsage objects with before and after GC
|
|
1910 // per pool memory usage
|
|
1911 objArrayOop bu = get_memory_usage_objArray(gc_stat->usage_before_gc,
|
|
1912 num_pools,
|
|
1913 CHECK);
|
|
1914 objArrayHandle usage_before_gc_ah(THREAD, bu);
|
|
1915
|
|
1916 objArrayOop au = get_memory_usage_objArray(gc_stat->usage_after_gc,
|
|
1917 num_pools,
|
|
1918 CHECK);
|
|
1919 objArrayHandle usage_after_gc_ah(THREAD, au);
|
|
1920
|
|
1921 for (int i = 0; i < num_pools; i++) {
|
|
1922 Handle before_usage = MemoryService::create_MemoryUsage_obj(stat->before_gc_usage_for_pool(i), CHECK);
|
|
1923 Handle after_usage;
|
|
1924
|
|
1925 MemoryUsage u = stat->after_gc_usage_for_pool(i);
|
|
1926 if (u.max_size() == 0 && u.used() > 0) {
|
|
1927 // If max size == 0, this pool is a survivor space.
|
|
1928 // Set max size = -1 since the pools will be swapped after GC.
|
|
1929 MemoryUsage usage(u.init_size(), u.used(), u.committed(), (size_t)-1);
|
|
1930 after_usage = MemoryService::create_MemoryUsage_obj(usage, CHECK);
|
|
1931 } else {
|
|
1932 after_usage = MemoryService::create_MemoryUsage_obj(stat->after_gc_usage_for_pool(i), CHECK);
|
|
1933 }
|
|
1934 usage_before_gc_ah->obj_at_put(i, before_usage());
|
|
1935 usage_after_gc_ah->obj_at_put(i, after_usage());
|
|
1936 }
|
|
1937
|
|
1938 if (gc_stat->gc_ext_attribute_values_size > 0) {
|
|
1939 // Current implementation only has 1 attribute (number of GC threads)
|
|
1940 // The type is 'I'
|
|
1941 gc_stat->gc_ext_attribute_values[0].i = mgr->num_gc_threads();
|
|
1942 }
|
|
1943 JVM_END
|
|
1944
|
|
1945 // Dump heap - Returns 0 if succeeds.
|
|
1946 JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live))
|
|
1947 #ifndef SERVICES_KERNEL
|
|
1948 ResourceMark rm(THREAD);
|
|
1949 oop on = JNIHandles::resolve_external_guard(outputfile);
|
|
1950 if (on == NULL) {
|
|
1951 THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
|
|
1952 "Output file name cannot be null.", -1);
|
|
1953 }
|
|
1954 char* name = java_lang_String::as_utf8_string(on);
|
|
1955 if (name == NULL) {
|
|
1956 THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
|
|
1957 "Output file name cannot be null.", -1);
|
|
1958 }
|
|
1959 HeapDumper dumper(live ? true : false);
|
|
1960 if (dumper.dump(name) != 0) {
|
|
1961 const char* errmsg = dumper.error_as_C_string();
|
|
1962 THROW_MSG_(vmSymbols::java_io_IOException(), errmsg, -1);
|
|
1963 }
|
|
1964 return 0;
|
|
1965 #else // SERVICES_KERNEL
|
|
1966 return -1;
|
|
1967 #endif // SERVICES_KERNEL
|
|
1968 JVM_END
|
|
1969
|
|
1970 jlong Management::ticks_to_ms(jlong ticks) {
|
|
1971 assert(os::elapsed_frequency() > 0, "Must be non-zero");
|
|
1972 return (jlong)(((double)ticks / (double)os::elapsed_frequency())
|
|
1973 * (double)1000.0);
|
|
1974 }
|
|
1975
|
|
1976 const struct jmmInterface_1_ jmm_interface = {
|
|
1977 NULL,
|
|
1978 NULL,
|
|
1979 jmm_GetVersion,
|
|
1980 jmm_GetOptionalSupport,
|
|
1981 jmm_GetInputArguments,
|
|
1982 jmm_GetThreadInfo,
|
|
1983 jmm_GetInputArgumentArray,
|
|
1984 jmm_GetMemoryPools,
|
|
1985 jmm_GetMemoryManagers,
|
|
1986 jmm_GetMemoryPoolUsage,
|
|
1987 jmm_GetPeakMemoryPoolUsage,
|
|
1988 NULL,
|
|
1989 jmm_GetMemoryUsage,
|
|
1990 jmm_GetLongAttribute,
|
|
1991 jmm_GetBoolAttribute,
|
|
1992 jmm_SetBoolAttribute,
|
|
1993 jmm_GetLongAttributes,
|
|
1994 jmm_FindMonitorDeadlockedThreads,
|
|
1995 jmm_GetThreadCpuTime,
|
|
1996 jmm_GetVMGlobalNames,
|
|
1997 jmm_GetVMGlobals,
|
|
1998 jmm_GetInternalThreadTimes,
|
|
1999 jmm_ResetStatistic,
|
|
2000 jmm_SetPoolSensor,
|
|
2001 jmm_SetPoolThreshold,
|
|
2002 jmm_GetPoolCollectionUsage,
|
|
2003 jmm_GetGCExtAttributeInfo,
|
|
2004 jmm_GetLastGCStat,
|
|
2005 jmm_GetThreadCpuTimeWithKind,
|
|
2006 NULL,
|
|
2007 jmm_DumpHeap0,
|
|
2008 jmm_FindDeadlockedThreads,
|
|
2009 jmm_SetVMGlobal,
|
|
2010 NULL,
|
|
2011 jmm_DumpThreads
|
|
2012 };
|
|
2013
|
|
2014 void* Management::get_jmm_interface(int version) {
|
|
2015 if (version == JMM_VERSION_1_0) {
|
|
2016 return (void*) &jmm_interface;
|
|
2017 }
|
|
2018 return NULL;
|
|
2019 }
|