Mercurial > hg > truffle
annotate src/share/vm/services/threadService.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
2 * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_threadService.cpp.incl" | |
27 | |
28 // TODO: we need to define a naming convention for perf counters | |
29 // to distinguish counters for: | |
30 // - standard JSR174 use | |
31 // - Hotspot extension (public and committed) | |
32 // - Hotspot extension (private/internal and uncommitted) | |
33 | |
34 // Default is disabled. | |
35 bool ThreadService::_thread_monitoring_contention_enabled = false; | |
36 bool ThreadService::_thread_cpu_time_enabled = false; | |
37 | |
38 PerfCounter* ThreadService::_total_threads_count = NULL; | |
39 PerfVariable* ThreadService::_live_threads_count = NULL; | |
40 PerfVariable* ThreadService::_peak_threads_count = NULL; | |
41 PerfVariable* ThreadService::_daemon_threads_count = NULL; | |
42 volatile int ThreadService::_exiting_threads_count = 0; | |
43 volatile int ThreadService::_exiting_daemon_threads_count = 0; | |
44 | |
45 ThreadDumpResult* ThreadService::_threaddump_list = NULL; | |
46 | |
47 static const int INITIAL_ARRAY_SIZE = 10; | |
48 | |
49 void ThreadService::init() { | |
50 EXCEPTION_MARK; | |
51 | |
52 // These counters are for java.lang.management API support. | |
53 // They are created even if -XX:-UsePerfData is set and in | |
54 // that case, they will be allocated on C heap. | |
55 | |
56 _total_threads_count = | |
57 PerfDataManager::create_counter(JAVA_THREADS, "started", | |
58 PerfData::U_Events, CHECK); | |
59 | |
60 _live_threads_count = | |
61 PerfDataManager::create_variable(JAVA_THREADS, "live", | |
62 PerfData::U_None, CHECK); | |
63 | |
64 _peak_threads_count = | |
65 PerfDataManager::create_variable(JAVA_THREADS, "livePeak", | |
66 PerfData::U_None, CHECK); | |
67 | |
68 _daemon_threads_count = | |
69 PerfDataManager::create_variable(JAVA_THREADS, "daemon", | |
70 PerfData::U_None, CHECK); | |
71 | |
72 if (os::is_thread_cpu_time_supported()) { | |
73 _thread_cpu_time_enabled = true; | |
74 } | |
75 } | |
76 | |
77 void ThreadService::reset_peak_thread_count() { | |
78 // Acquire the lock to update the peak thread count | |
79 // to synchronize with thread addition and removal. | |
80 MutexLockerEx mu(Threads_lock); | |
81 _peak_threads_count->set_value(get_live_thread_count()); | |
82 } | |
83 | |
84 void ThreadService::add_thread(JavaThread* thread, bool daemon) { | |
85 // Do not count VM internal or JVMTI agent threads | |
86 if (thread->is_hidden_from_external_view() || | |
87 thread->is_jvmti_agent_thread()) { | |
88 return; | |
89 } | |
90 | |
91 _total_threads_count->inc(); | |
92 _live_threads_count->inc(); | |
93 | |
94 if (_live_threads_count->get_value() > _peak_threads_count->get_value()) { | |
95 _peak_threads_count->set_value(_live_threads_count->get_value()); | |
96 } | |
97 | |
98 if (daemon) { | |
99 _daemon_threads_count->inc(); | |
100 } | |
101 } | |
102 | |
103 void ThreadService::remove_thread(JavaThread* thread, bool daemon) { | |
104 Atomic::dec((jint*) &_exiting_threads_count); | |
105 | |
106 if (thread->is_hidden_from_external_view() || | |
107 thread->is_jvmti_agent_thread()) { | |
108 return; | |
109 } | |
110 | |
111 _live_threads_count->set_value(_live_threads_count->get_value() - 1); | |
112 | |
113 if (daemon) { | |
114 _daemon_threads_count->set_value(_daemon_threads_count->get_value() - 1); | |
115 Atomic::dec((jint*) &_exiting_daemon_threads_count); | |
116 } | |
117 } | |
118 | |
119 void ThreadService::current_thread_exiting(JavaThread* jt) { | |
120 assert(jt == JavaThread::current(), "Called by current thread"); | |
121 Atomic::inc((jint*) &_exiting_threads_count); | |
122 | |
123 oop threadObj = jt->threadObj(); | |
124 if (threadObj != NULL && java_lang_Thread::is_daemon(threadObj)) { | |
125 Atomic::inc((jint*) &_exiting_daemon_threads_count); | |
126 } | |
127 } | |
128 | |
129 // FIXME: JVMTI should call this function | |
130 Handle ThreadService::get_current_contended_monitor(JavaThread* thread) { | |
131 assert(thread != NULL, "should be non-NULL"); | |
132 assert(Threads_lock->owned_by_self(), "must grab Threads_lock or be at safepoint"); | |
133 | |
134 ObjectMonitor *wait_obj = thread->current_waiting_monitor(); | |
135 | |
136 oop obj = NULL; | |
137 if (wait_obj != NULL) { | |
138 // thread is doing an Object.wait() call | |
139 obj = (oop) wait_obj->object(); | |
140 assert(obj != NULL, "Object.wait() should have an object"); | |
141 } else { | |
142 ObjectMonitor *enter_obj = thread->current_pending_monitor(); | |
143 if (enter_obj != NULL) { | |
144 // thread is trying to enter() or raw_enter() an ObjectMonitor. | |
145 obj = (oop) enter_obj->object(); | |
146 } | |
147 // If obj == NULL, then ObjectMonitor is raw which doesn't count. | |
148 } | |
149 | |
150 Handle h(obj); | |
151 return h; | |
152 } | |
153 | |
154 bool ThreadService::set_thread_monitoring_contention(bool flag) { | |
155 MutexLocker m(Management_lock); | |
156 | |
157 bool prev = _thread_monitoring_contention_enabled; | |
158 _thread_monitoring_contention_enabled = flag; | |
159 | |
160 return prev; | |
161 } | |
162 | |
163 bool ThreadService::set_thread_cpu_time_enabled(bool flag) { | |
164 MutexLocker m(Management_lock); | |
165 | |
166 bool prev = _thread_cpu_time_enabled; | |
167 _thread_cpu_time_enabled = flag; | |
168 | |
169 return prev; | |
170 } | |
171 | |
172 // GC support | |
173 void ThreadService::oops_do(OopClosure* f) { | |
174 for (ThreadDumpResult* dump = _threaddump_list; dump != NULL; dump = dump->next()) { | |
175 dump->oops_do(f); | |
176 } | |
177 } | |
178 | |
179 void ThreadService::add_thread_dump(ThreadDumpResult* dump) { | |
180 MutexLocker ml(Management_lock); | |
181 if (_threaddump_list == NULL) { | |
182 _threaddump_list = dump; | |
183 } else { | |
184 dump->set_next(_threaddump_list); | |
185 _threaddump_list = dump; | |
186 } | |
187 } | |
188 | |
189 void ThreadService::remove_thread_dump(ThreadDumpResult* dump) { | |
190 MutexLocker ml(Management_lock); | |
191 | |
192 ThreadDumpResult* prev = NULL; | |
193 bool found = false; | |
194 for (ThreadDumpResult* d = _threaddump_list; d != NULL; prev = d, d = d->next()) { | |
195 if (d == dump) { | |
196 if (prev == NULL) { | |
197 _threaddump_list = dump->next(); | |
198 } else { | |
199 prev->set_next(dump->next()); | |
200 } | |
201 found = true; | |
202 break; | |
203 } | |
204 } | |
205 assert(found, "The threaddump result to be removed must exist."); | |
206 } | |
207 | |
208 // Dump stack trace of threads specified in the given threads array. | |
209 // Returns StackTraceElement[][] each element is the stack trace of a thread in | |
210 // the corresponding entry in the given threads array | |
211 Handle ThreadService::dump_stack_traces(GrowableArray<instanceHandle>* threads, | |
212 int num_threads, | |
213 TRAPS) { | |
214 assert(num_threads > 0, "just checking"); | |
215 | |
216 ThreadDumpResult dump_result; | |
217 VM_ThreadDump op(&dump_result, | |
218 threads, | |
219 num_threads, | |
220 -1, /* entire stack */ | |
221 false, /* with locked monitors */ | |
222 false /* with locked synchronizers */); | |
223 VMThread::execute(&op); | |
224 | |
225 // Allocate the resulting StackTraceElement[][] object | |
226 | |
227 ResourceMark rm(THREAD); | |
228 klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_StackTraceElement_array(), true, CHECK_NH); | |
229 objArrayKlassHandle ik (THREAD, k); | |
230 objArrayOop r = oopFactory::new_objArray(ik(), num_threads, CHECK_NH); | |
231 objArrayHandle result_obj(THREAD, r); | |
232 | |
233 int num_snapshots = dump_result.num_snapshots(); | |
234 assert(num_snapshots == num_threads, "Must have num_threads thread snapshots"); | |
235 int i = 0; | |
236 for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; i++, ts = ts->next()) { | |
237 ThreadStackTrace* stacktrace = ts->get_stack_trace(); | |
238 if (stacktrace == NULL) { | |
239 // No stack trace | |
240 result_obj->obj_at_put(i, NULL); | |
241 } else { | |
242 // Construct an array of java/lang/StackTraceElement object | |
243 Handle backtrace_h = stacktrace->allocate_fill_stack_trace_element_array(CHECK_NH); | |
244 result_obj->obj_at_put(i, backtrace_h()); | |
245 } | |
246 } | |
247 | |
248 return result_obj; | |
249 } | |
250 | |
251 void ThreadService::reset_contention_count_stat(JavaThread* thread) { | |
252 ThreadStatistics* stat = thread->get_thread_stat(); | |
253 if (stat != NULL) { | |
254 stat->reset_count_stat(); | |
255 } | |
256 } | |
257 | |
258 void ThreadService::reset_contention_time_stat(JavaThread* thread) { | |
259 ThreadStatistics* stat = thread->get_thread_stat(); | |
260 if (stat != NULL) { | |
261 stat->reset_time_stat(); | |
262 } | |
263 } | |
264 | |
265 // Find deadlocks involving object monitors and concurrent locks if concurrent_locks is true | |
266 DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) { | |
267 // This code was modified from the original Threads::find_deadlocks code. | |
268 int globalDfn = 0, thisDfn; | |
269 ObjectMonitor* waitingToLockMonitor = NULL; | |
270 oop waitingToLockBlocker = NULL; | |
271 bool blocked_on_monitor = false; | |
272 JavaThread *currentThread, *previousThread; | |
273 int num_deadlocks = 0; | |
274 | |
275 for (JavaThread* p = Threads::first(); p != NULL; p = p->next()) { | |
276 // Initialize the depth-first-number | |
277 p->set_depth_first_number(-1); | |
278 } | |
279 | |
280 DeadlockCycle* deadlocks = NULL; | |
281 DeadlockCycle* last = NULL; | |
282 DeadlockCycle* cycle = new DeadlockCycle(); | |
283 for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { | |
284 if (jt->depth_first_number() >= 0) { | |
285 // this thread was already visited | |
286 continue; | |
287 } | |
288 | |
289 thisDfn = globalDfn; | |
290 jt->set_depth_first_number(globalDfn++); | |
291 previousThread = jt; | |
292 currentThread = jt; | |
293 | |
294 cycle->reset(); | |
295 | |
296 // When there is a deadlock, all the monitors involved in the dependency | |
297 // cycle must be contended and heavyweight. So we only care about the | |
298 // heavyweight monitor a thread is waiting to lock. | |
299 waitingToLockMonitor = (ObjectMonitor*)jt->current_pending_monitor(); | |
300 if (concurrent_locks) { | |
301 waitingToLockBlocker = jt->current_park_blocker(); | |
302 } | |
303 while (waitingToLockMonitor != NULL || waitingToLockBlocker != NULL) { | |
304 cycle->add_thread(currentThread); | |
305 if (waitingToLockMonitor != NULL) { | |
306 currentThread = Threads::owning_thread_from_monitor_owner((address)waitingToLockMonitor->owner(), | |
307 false /* no locking needed */); | |
308 } else { | |
309 if (concurrent_locks) { | |
310 if (waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass())) { | |
311 oop threadObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker); | |
312 currentThread = threadObj != NULL ? java_lang_Thread::thread(threadObj) : NULL; | |
313 } else { | |
314 currentThread = NULL; | |
315 } | |
316 } | |
317 } | |
318 | |
319 if (currentThread == NULL) { | |
320 // No dependency on another thread | |
321 break; | |
322 } | |
323 if (currentThread->depth_first_number() < 0) { | |
324 // First visit to this thread | |
325 currentThread->set_depth_first_number(globalDfn++); | |
326 } else if (currentThread->depth_first_number() < thisDfn) { | |
327 // Thread already visited, and not on a (new) cycle | |
328 break; | |
329 } else if (currentThread == previousThread) { | |
330 // Self-loop, ignore | |
331 break; | |
332 } else { | |
333 // We have a (new) cycle | |
334 num_deadlocks++; | |
335 | |
336 cycle->set_deadlock(true); | |
337 | |
338 // add this cycle to the deadlocks list | |
339 if (deadlocks == NULL) { | |
340 deadlocks = cycle; | |
341 } else { | |
342 last->set_next(cycle); | |
343 } | |
344 last = cycle; | |
345 cycle = new DeadlockCycle(); | |
346 break; | |
347 } | |
348 previousThread = currentThread; | |
349 waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor(); | |
350 if (concurrent_locks) { | |
351 waitingToLockBlocker = currentThread->current_park_blocker(); | |
352 } | |
353 } | |
354 | |
355 } | |
356 | |
357 return deadlocks; | |
358 } | |
359 | |
360 ThreadDumpResult::ThreadDumpResult() : _num_threads(0), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL) { | |
361 | |
362 // Create a new ThreadDumpResult object and append to the list. | |
363 // If GC happens before this function returns, methodOop | |
364 // in the stack trace will be visited. | |
365 ThreadService::add_thread_dump(this); | |
366 } | |
367 | |
368 ThreadDumpResult::ThreadDumpResult(int num_threads) : _num_threads(num_threads), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL) { | |
369 // Create a new ThreadDumpResult object and append to the list. | |
370 // If GC happens before this function returns, oops | |
371 // will be visited. | |
372 ThreadService::add_thread_dump(this); | |
373 } | |
374 | |
375 ThreadDumpResult::~ThreadDumpResult() { | |
376 ThreadService::remove_thread_dump(this); | |
377 | |
378 // free all the ThreadSnapshot objects created during | |
379 // the VM_ThreadDump operation | |
380 ThreadSnapshot* ts = _snapshots; | |
381 while (ts != NULL) { | |
382 ThreadSnapshot* p = ts; | |
383 ts = ts->next(); | |
384 delete p; | |
385 } | |
386 } | |
387 | |
388 | |
389 void ThreadDumpResult::add_thread_snapshot(ThreadSnapshot* ts) { | |
390 assert(_num_threads == 0 || _num_snapshots < _num_threads, | |
391 "_num_snapshots must be less than _num_threads"); | |
392 _num_snapshots++; | |
393 if (_snapshots == NULL) { | |
394 _snapshots = ts; | |
395 } else { | |
396 _last->set_next(ts); | |
397 } | |
398 _last = ts; | |
399 } | |
400 | |
401 void ThreadDumpResult::oops_do(OopClosure* f) { | |
402 for (ThreadSnapshot* ts = _snapshots; ts != NULL; ts = ts->next()) { | |
403 ts->oops_do(f); | |
404 } | |
405 } | |
406 | |
407 StackFrameInfo::StackFrameInfo(javaVFrame* jvf, bool with_lock_info) { | |
408 _method = jvf->method(); | |
409 _bci = jvf->bci(); | |
410 _locked_monitors = NULL; | |
411 if (with_lock_info) { | |
412 ResourceMark rm; | |
413 GrowableArray<MonitorInfo*>* list = jvf->locked_monitors(); | |
414 int length = list->length(); | |
415 if (length > 0) { | |
416 _locked_monitors = new (ResourceObj::C_HEAP) GrowableArray<oop>(length, true); | |
417 for (int i = 0; i < length; i++) { | |
418 MonitorInfo* monitor = list->at(i); | |
419 assert(monitor->owner(), "This monitor must have an owning object"); | |
420 _locked_monitors->append(monitor->owner()); | |
421 } | |
422 } | |
423 } | |
424 } | |
425 | |
426 void StackFrameInfo::oops_do(OopClosure* f) { | |
427 f->do_oop((oop*) &_method); | |
428 if (_locked_monitors != NULL) { | |
429 int length = _locked_monitors->length(); | |
430 for (int i = 0; i < length; i++) { | |
431 f->do_oop((oop*) _locked_monitors->adr_at(i)); | |
432 } | |
433 } | |
434 } | |
435 | |
436 void StackFrameInfo::print_on(outputStream* st) const { | |
437 ResourceMark rm; | |
438 java_lang_Throwable::print_stack_element(st, method(), bci()); | |
439 int len = (_locked_monitors != NULL ? _locked_monitors->length() : 0); | |
440 for (int i = 0; i < len; i++) { | |
441 oop o = _locked_monitors->at(i); | |
442 instanceKlass* ik = instanceKlass::cast(o->klass()); | |
443 st->print_cr("\t- locked <" INTPTR_FORMAT "> (a %s)", (address)o, ik->external_name()); | |
444 } | |
445 | |
446 } | |
447 | |
448 // Iterate through monitor cache to find JNI locked monitors | |
449 class InflatedMonitorsClosure: public MonitorClosure { | |
450 private: | |
451 ThreadStackTrace* _stack_trace; | |
452 Thread* _thread; | |
453 public: | |
454 InflatedMonitorsClosure(Thread* t, ThreadStackTrace* st) { | |
455 _thread = t; | |
456 _stack_trace = st; | |
457 } | |
458 void do_monitor(ObjectMonitor* mid) { | |
459 if (mid->owner() == _thread) { | |
460 oop object = (oop) mid->object(); | |
461 if (!_stack_trace->is_owned_monitor_on_stack(object)) { | |
462 _stack_trace->add_jni_locked_monitor(object); | |
463 } | |
464 } | |
465 } | |
466 }; | |
467 | |
468 ThreadStackTrace::ThreadStackTrace(JavaThread* t, bool with_locked_monitors) { | |
469 _thread = t; | |
470 _frames = new (ResourceObj::C_HEAP) GrowableArray<StackFrameInfo*>(INITIAL_ARRAY_SIZE, true); | |
471 _depth = 0; | |
472 _with_locked_monitors = with_locked_monitors; | |
473 if (_with_locked_monitors) { | |
474 _jni_locked_monitors = new (ResourceObj::C_HEAP) GrowableArray<oop>(INITIAL_ARRAY_SIZE, true); | |
475 } else { | |
476 _jni_locked_monitors = NULL; | |
477 } | |
478 } | |
479 | |
480 ThreadStackTrace::~ThreadStackTrace() { | |
481 for (int i = 0; i < _frames->length(); i++) { | |
482 delete _frames->at(i); | |
483 } | |
484 delete _frames; | |
485 if (_jni_locked_monitors != NULL) { | |
486 delete _jni_locked_monitors; | |
487 } | |
488 } | |
489 | |
490 void ThreadStackTrace::dump_stack_at_safepoint(int maxDepth) { | |
491 assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped"); | |
492 | |
493 if (_thread->has_last_Java_frame()) { | |
494 RegisterMap reg_map(_thread); | |
495 vframe* start_vf = _thread->last_java_vframe(®_map); | |
496 int count = 0; | |
497 for (vframe* f = start_vf; f; f = f->sender() ) { | |
498 if (f->is_java_frame()) { | |
499 javaVFrame* jvf = javaVFrame::cast(f); | |
500 add_stack_frame(jvf); | |
501 count++; | |
502 } else { | |
503 // Ignore non-Java frames | |
504 } | |
505 if (maxDepth > 0 && count == maxDepth) { | |
506 // Skip frames if more than maxDepth | |
507 break; | |
508 } | |
509 } | |
510 } | |
511 | |
512 if (_with_locked_monitors) { | |
513 // Iterate inflated monitors and find monitors locked by this thread | |
514 // not found in the stack | |
515 InflatedMonitorsClosure imc(_thread, this); | |
516 ObjectSynchronizer::monitors_iterate(&imc); | |
517 } | |
518 } | |
519 | |
520 | |
521 bool ThreadStackTrace::is_owned_monitor_on_stack(oop object) { | |
522 assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped"); | |
523 | |
524 bool found = false; | |
525 int num_frames = get_stack_depth(); | |
526 for (int depth = 0; depth < num_frames; depth++) { | |
527 StackFrameInfo* frame = stack_frame_at(depth); | |
528 int len = frame->num_locked_monitors(); | |
529 GrowableArray<oop>* locked_monitors = frame->locked_monitors(); | |
530 for (int j = 0; j < len; j++) { | |
531 oop monitor = locked_monitors->at(j); | |
532 assert(monitor != NULL && monitor->is_instance(), "must be a Java object"); | |
533 if (monitor == object) { | |
534 found = true; | |
535 break; | |
536 } | |
537 } | |
538 } | |
539 return found; | |
540 } | |
541 | |
542 Handle ThreadStackTrace::allocate_fill_stack_trace_element_array(TRAPS) { | |
1142 | 543 klassOop k = SystemDictionary::StackTraceElement_klass(); |
132
60b728ec77c1
6652736: well known classes in system dictionary are inefficiently processed
jrose
parents:
0
diff
changeset
|
544 assert(k != NULL, "must be loaded in 1.4+"); |
0 | 545 instanceKlassHandle ik(THREAD, k); |
546 | |
547 // Allocate an array of java/lang/StackTraceElement object | |
548 objArrayOop ste = oopFactory::new_objArray(ik(), _depth, CHECK_NH); | |
549 objArrayHandle backtrace(THREAD, ste); | |
550 for (int j = 0; j < _depth; j++) { | |
551 StackFrameInfo* frame = _frames->at(j); | |
552 methodHandle mh(THREAD, frame->method()); | |
553 oop element = java_lang_StackTraceElement::create(mh, frame->bci(), CHECK_NH); | |
554 backtrace->obj_at_put(j, element); | |
555 } | |
556 return backtrace; | |
557 } | |
558 | |
559 void ThreadStackTrace::add_stack_frame(javaVFrame* jvf) { | |
560 StackFrameInfo* frame = new StackFrameInfo(jvf, _with_locked_monitors); | |
561 _frames->append(frame); | |
562 _depth++; | |
563 } | |
564 | |
565 void ThreadStackTrace::oops_do(OopClosure* f) { | |
566 int length = _frames->length(); | |
567 for (int i = 0; i < length; i++) { | |
568 _frames->at(i)->oops_do(f); | |
569 } | |
570 | |
571 length = (_jni_locked_monitors != NULL ? _jni_locked_monitors->length() : 0); | |
572 for (int j = 0; j < length; j++) { | |
573 f->do_oop((oop*) _jni_locked_monitors->adr_at(j)); | |
574 } | |
575 } | |
576 | |
577 ConcurrentLocksDump::~ConcurrentLocksDump() { | |
578 if (_retain_map_on_free) { | |
579 return; | |
580 } | |
581 | |
582 for (ThreadConcurrentLocks* t = _map; t != NULL;) { | |
583 ThreadConcurrentLocks* tcl = t; | |
584 t = t->next(); | |
585 delete tcl; | |
586 } | |
587 } | |
588 | |
589 void ConcurrentLocksDump::dump_at_safepoint() { | |
590 // dump all locked concurrent locks | |
591 assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped"); | |
592 | |
593 if (JDK_Version::is_gte_jdk16x_version()) { | |
594 ResourceMark rm; | |
595 | |
596 GrowableArray<oop>* aos_objects = new GrowableArray<oop>(INITIAL_ARRAY_SIZE); | |
597 | |
598 // Find all instances of AbstractOwnableSynchronizer | |
599 HeapInspection::find_instances_at_safepoint(SystemDictionary::abstract_ownable_synchronizer_klass(), | |
600 aos_objects); | |
601 // Build a map of thread to its owned AQS locks | |
602 build_map(aos_objects); | |
603 } | |
604 } | |
605 | |
606 | |
607 // build a map of JavaThread to all its owned AbstractOwnableSynchronizer | |
608 void ConcurrentLocksDump::build_map(GrowableArray<oop>* aos_objects) { | |
609 int length = aos_objects->length(); | |
610 for (int i = 0; i < length; i++) { | |
611 oop o = aos_objects->at(i); | |
612 oop owner_thread_obj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(o); | |
613 if (owner_thread_obj != NULL) { | |
614 JavaThread* thread = java_lang_Thread::thread(owner_thread_obj); | |
615 assert(o->is_instance(), "Must be an instanceOop"); | |
616 add_lock(thread, (instanceOop) o); | |
617 } | |
618 } | |
619 } | |
620 | |
621 void ConcurrentLocksDump::add_lock(JavaThread* thread, instanceOop o) { | |
622 ThreadConcurrentLocks* tcl = thread_concurrent_locks(thread); | |
623 if (tcl != NULL) { | |
624 tcl->add_lock(o); | |
625 return; | |
626 } | |
627 | |
628 // First owned lock found for this thread | |
629 tcl = new ThreadConcurrentLocks(thread); | |
630 tcl->add_lock(o); | |
631 if (_map == NULL) { | |
632 _map = tcl; | |
633 } else { | |
634 _last->set_next(tcl); | |
635 } | |
636 _last = tcl; | |
637 } | |
638 | |
639 ThreadConcurrentLocks* ConcurrentLocksDump::thread_concurrent_locks(JavaThread* thread) { | |
640 for (ThreadConcurrentLocks* tcl = _map; tcl != NULL; tcl = tcl->next()) { | |
641 if (tcl->java_thread() == thread) { | |
642 return tcl; | |
643 } | |
644 } | |
645 return NULL; | |
646 } | |
647 | |
648 void ConcurrentLocksDump::print_locks_on(JavaThread* t, outputStream* st) { | |
649 st->print_cr(" Locked ownable synchronizers:"); | |
650 ThreadConcurrentLocks* tcl = thread_concurrent_locks(t); | |
651 GrowableArray<instanceOop>* locks = (tcl != NULL ? tcl->owned_locks() : NULL); | |
652 if (locks == NULL || locks->is_empty()) { | |
653 st->print_cr("\t- None"); | |
654 st->cr(); | |
655 return; | |
656 } | |
657 | |
658 for (int i = 0; i < locks->length(); i++) { | |
659 instanceOop obj = locks->at(i); | |
660 instanceKlass* ik = instanceKlass::cast(obj->klass()); | |
661 st->print_cr("\t- <" INTPTR_FORMAT "> (a %s)", (address)obj, ik->external_name()); | |
662 } | |
663 st->cr(); | |
664 } | |
665 | |
666 ThreadConcurrentLocks::ThreadConcurrentLocks(JavaThread* thread) { | |
667 _thread = thread; | |
668 _owned_locks = new (ResourceObj::C_HEAP) GrowableArray<instanceOop>(INITIAL_ARRAY_SIZE, true); | |
669 _next = NULL; | |
670 } | |
671 | |
672 ThreadConcurrentLocks::~ThreadConcurrentLocks() { | |
673 delete _owned_locks; | |
674 } | |
675 | |
676 void ThreadConcurrentLocks::add_lock(instanceOop o) { | |
677 _owned_locks->append(o); | |
678 } | |
679 | |
680 void ThreadConcurrentLocks::oops_do(OopClosure* f) { | |
681 int length = _owned_locks->length(); | |
682 for (int i = 0; i < length; i++) { | |
683 f->do_oop((oop*) _owned_locks->adr_at(i)); | |
684 } | |
685 } | |
686 | |
687 ThreadStatistics::ThreadStatistics() { | |
688 _contended_enter_count = 0; | |
689 _monitor_wait_count = 0; | |
690 _sleep_count = 0; | |
691 _count_pending_reset = false; | |
692 _timer_pending_reset = false; | |
875
6a93908f268f
6857194: Add hotspot perf counters to aid class loading performance measurement
mchung
parents:
242
diff
changeset
|
693 memset((void*) _perf_recursion_counts, 0, sizeof(_perf_recursion_counts)); |
0 | 694 } |
695 | |
696 ThreadSnapshot::ThreadSnapshot(JavaThread* thread) { | |
697 _thread = thread; | |
698 _threadObj = thread->threadObj(); | |
699 _stack_trace = NULL; | |
700 _concurrent_locks = NULL; | |
701 _next = NULL; | |
702 | |
703 ThreadStatistics* stat = thread->get_thread_stat(); | |
704 _contended_enter_ticks = stat->contended_enter_ticks(); | |
705 _contended_enter_count = stat->contended_enter_count(); | |
706 _monitor_wait_ticks = stat->monitor_wait_ticks(); | |
707 _monitor_wait_count = stat->monitor_wait_count(); | |
708 _sleep_ticks = stat->sleep_ticks(); | |
709 _sleep_count = stat->sleep_count(); | |
710 | |
711 _blocker_object = NULL; | |
712 _blocker_object_owner = NULL; | |
713 | |
714 _thread_status = java_lang_Thread::get_thread_status(_threadObj); | |
715 _is_ext_suspended = thread->is_being_ext_suspended(); | |
716 _is_in_native = (thread->thread_state() == _thread_in_native); | |
717 | |
718 if (_thread_status == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER || | |
719 _thread_status == java_lang_Thread::IN_OBJECT_WAIT || | |
720 _thread_status == java_lang_Thread::IN_OBJECT_WAIT_TIMED) { | |
721 | |
722 Handle obj = ThreadService::get_current_contended_monitor(thread); | |
723 if (obj() == NULL) { | |
724 // monitor no longer exists; thread is not blocked | |
725 _thread_status = java_lang_Thread::RUNNABLE; | |
726 } else { | |
727 _blocker_object = obj(); | |
728 JavaThread* owner = ObjectSynchronizer::get_lock_owner(obj, false); | |
729 if ((owner == NULL && _thread_status == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER) | |
730 || (owner != NULL && owner->is_attaching())) { | |
731 // ownership information of the monitor is not available | |
732 // (may no longer be owned or releasing to some other thread) | |
733 // make this thread in RUNNABLE state. | |
734 // And when the owner thread is in attaching state, the java thread | |
735 // is not completely initialized. For example thread name and id | |
736 // and may not be set, so hide the attaching thread. | |
737 _thread_status = java_lang_Thread::RUNNABLE; | |
738 _blocker_object = NULL; | |
739 } else if (owner != NULL) { | |
740 _blocker_object_owner = owner->threadObj(); | |
741 } | |
742 } | |
743 } | |
744 | |
745 // Support for JSR-166 locks | |
242 | 746 if (JDK_Version::current().supports_thread_park_blocker() && |
0 | 747 (_thread_status == java_lang_Thread::PARKED || |
748 _thread_status == java_lang_Thread::PARKED_TIMED)) { | |
749 | |
750 _blocker_object = thread->current_park_blocker(); | |
751 if (_blocker_object != NULL && _blocker_object->is_a(SystemDictionary::abstract_ownable_synchronizer_klass())) { | |
752 _blocker_object_owner = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(_blocker_object); | |
753 } | |
754 } | |
755 } | |
756 | |
757 ThreadSnapshot::~ThreadSnapshot() { | |
758 delete _stack_trace; | |
759 delete _concurrent_locks; | |
760 } | |
761 | |
762 void ThreadSnapshot::dump_stack_at_safepoint(int max_depth, bool with_locked_monitors) { | |
763 _stack_trace = new ThreadStackTrace(_thread, with_locked_monitors); | |
764 _stack_trace->dump_stack_at_safepoint(max_depth); | |
765 } | |
766 | |
767 | |
768 void ThreadSnapshot::oops_do(OopClosure* f) { | |
769 f->do_oop(&_threadObj); | |
770 f->do_oop(&_blocker_object); | |
771 f->do_oop(&_blocker_object_owner); | |
772 if (_stack_trace != NULL) { | |
773 _stack_trace->oops_do(f); | |
774 } | |
775 if (_concurrent_locks != NULL) { | |
776 _concurrent_locks->oops_do(f); | |
777 } | |
778 } | |
779 | |
780 DeadlockCycle::DeadlockCycle() { | |
781 _is_deadlock = false; | |
782 _threads = new (ResourceObj::C_HEAP) GrowableArray<JavaThread*>(INITIAL_ARRAY_SIZE, true); | |
783 _next = NULL; | |
784 } | |
785 | |
786 DeadlockCycle::~DeadlockCycle() { | |
787 delete _threads; | |
788 } | |
789 | |
790 void DeadlockCycle::print_on(outputStream* st) const { | |
791 st->cr(); | |
792 st->print_cr("Found one Java-level deadlock:"); | |
793 st->print("============================="); | |
794 | |
795 JavaThread* currentThread; | |
796 ObjectMonitor* waitingToLockMonitor; | |
797 oop waitingToLockBlocker; | |
798 int len = _threads->length(); | |
799 for (int i = 0; i < len; i++) { | |
800 currentThread = _threads->at(i); | |
801 waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor(); | |
802 waitingToLockBlocker = currentThread->current_park_blocker(); | |
803 st->cr(); | |
804 st->print_cr("\"%s\":", currentThread->get_thread_name()); | |
805 const char* owner_desc = ",\n which is held by"; | |
806 if (waitingToLockMonitor != NULL) { | |
807 st->print(" waiting to lock monitor " INTPTR_FORMAT, waitingToLockMonitor); | |
808 oop obj = (oop)waitingToLockMonitor->object(); | |
809 if (obj != NULL) { | |
810 st->print(" (object "INTPTR_FORMAT ", a %s)", (address)obj, | |
811 (instanceKlass::cast(obj->klass()))->external_name()); | |
812 | |
813 if (!currentThread->current_pending_monitor_is_from_java()) { | |
814 owner_desc = "\n in JNI, which is held by"; | |
815 } | |
816 } else { | |
817 // No Java object associated - a JVMTI raw monitor | |
818 owner_desc = " (JVMTI raw monitor),\n which is held by"; | |
819 } | |
820 currentThread = Threads::owning_thread_from_monitor_owner( | |
821 (address)waitingToLockMonitor->owner(), false /* no locking needed */); | |
822 } else { | |
823 st->print(" waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)", | |
824 (address)waitingToLockBlocker, | |
825 (instanceKlass::cast(waitingToLockBlocker->klass()))->external_name()); | |
826 assert(waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass()), | |
827 "Must be an AbstractOwnableSynchronizer"); | |
828 oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker); | |
829 currentThread = java_lang_Thread::thread(ownerObj); | |
830 } | |
831 st->print("%s \"%s\"", owner_desc, currentThread->get_thread_name()); | |
832 } | |
833 | |
834 st->cr(); | |
835 st->cr(); | |
836 | |
837 // Print stack traces | |
838 bool oldJavaMonitorsInStackTrace = JavaMonitorsInStackTrace; | |
839 JavaMonitorsInStackTrace = true; | |
840 st->print_cr("Java stack information for the threads listed above:"); | |
841 st->print_cr("==================================================="); | |
842 for (int j = 0; j < len; j++) { | |
843 currentThread = _threads->at(j); | |
844 st->print_cr("\"%s\":", currentThread->get_thread_name()); | |
845 currentThread->print_stack_on(st); | |
846 } | |
847 JavaMonitorsInStackTrace = oldJavaMonitorsInStackTrace; | |
848 } | |
849 | |
850 ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread, | |
851 bool include_jvmti_agent_threads, | |
852 bool include_jni_attaching_threads) { | |
853 assert(cur_thread == Thread::current(), "Check current thread"); | |
854 | |
855 int init_size = ThreadService::get_live_thread_count(); | |
856 _threads_array = new GrowableArray<instanceHandle>(init_size); | |
857 | |
858 MutexLockerEx ml(Threads_lock); | |
859 | |
860 for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { | |
861 // skips JavaThreads in the process of exiting | |
862 // and also skips VM internal JavaThreads | |
863 // Threads in _thread_new or _thread_new_trans state are included. | |
864 // i.e. threads have been started but not yet running. | |
865 if (jt->threadObj() == NULL || | |
866 jt->is_exiting() || | |
867 !java_lang_Thread::is_alive(jt->threadObj()) || | |
868 jt->is_hidden_from_external_view()) { | |
869 continue; | |
870 } | |
871 | |
872 // skip agent threads | |
873 if (!include_jvmti_agent_threads && jt->is_jvmti_agent_thread()) { | |
874 continue; | |
875 } | |
876 | |
877 // skip jni threads in the process of attaching | |
878 if (!include_jni_attaching_threads && jt->is_attaching()) { | |
879 continue; | |
880 } | |
881 | |
882 instanceHandle h(cur_thread, (instanceOop) jt->threadObj()); | |
883 _threads_array->append(h); | |
884 } | |
885 } |