Skip to content

Commit 8412479

Browse files
author
David Holmes
committed
8316229: Enhance class initialization logging
Reviewed-by: shade, coleenp
1 parent c04c9ea commit 8412479

File tree

4 files changed

+72
-4
lines changed

4 files changed

+72
-4
lines changed

src/hotspot/share/oops/instanceKlass.cpp

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -770,20 +770,43 @@ void InstanceKlass::link_class(TRAPS) {
770770
void InstanceKlass::check_link_state_and_wait(JavaThread* current) {
771771
MonitorLocker ml(current, _init_monitor);
772772

773+
bool debug_logging_enabled = log_is_enabled(Debug, class, init);
774+
773775
// Another thread is linking this class, wait.
774776
while (is_being_linked() && !is_init_thread(current)) {
777+
if (debug_logging_enabled) {
778+
ResourceMark rm(current);
779+
log_debug(class, init)("Thread \"%s\" waiting for linking of %s by thread \"%s\"",
780+
current->name(), external_name(), init_thread_name());
781+
}
775782
ml.wait();
776783
}
777784

778785
// This thread is recursively linking this class, continue
779786
if (is_being_linked() && is_init_thread(current)) {
787+
if (debug_logging_enabled) {
788+
ResourceMark rm(current);
789+
log_debug(class, init)("Thread \"%s\" recursively linking %s",
790+
current->name(), external_name());
791+
}
780792
return;
781793
}
782794

783795
// If this class wasn't linked already, set state to being_linked
784796
if (!is_linked()) {
797+
if (debug_logging_enabled) {
798+
ResourceMark rm(current);
799+
log_debug(class, init)("Thread \"%s\" linking %s",
800+
current->name(), external_name());
801+
}
785802
set_init_state(being_linked);
786803
set_init_thread(current);
804+
} else {
805+
if (debug_logging_enabled) {
806+
ResourceMark rm(current);
807+
log_debug(class, init)("Thread \"%s\" found %s already linked",
808+
current->name(), external_name());
809+
}
787810
}
788811
}
789812

@@ -1058,13 +1081,21 @@ void InstanceKlass::initialize_impl(TRAPS) {
10581081

10591082
JavaThread* jt = THREAD;
10601083

1084+
bool debug_logging_enabled = log_is_enabled(Debug, class, init);
1085+
10611086
// refer to the JVM book page 47 for description of steps
10621087
// Step 1
10631088
{
1064-
MonitorLocker ml(THREAD, _init_monitor);
1089+
MonitorLocker ml(jt, _init_monitor);
10651090

10661091
// Step 2
10671092
while (is_being_initialized() && !is_init_thread(jt)) {
1093+
if (debug_logging_enabled) {
1094+
ResourceMark rm(jt);
1095+
log_debug(class, init)("Thread \"%s\" waiting for initialization of %s by thread \"%s\"",
1096+
jt->name(), external_name(), init_thread_name());
1097+
}
1098+
10681099
wait = true;
10691100
jt->set_class_to_be_initialized(this);
10701101
ml.wait();
@@ -1073,24 +1104,44 @@ void InstanceKlass::initialize_impl(TRAPS) {
10731104

10741105
// Step 3
10751106
if (is_being_initialized() && is_init_thread(jt)) {
1107+
if (debug_logging_enabled) {
1108+
ResourceMark rm(jt);
1109+
log_debug(class, init)("Thread \"%s\" recursively initializing %s",
1110+
jt->name(), external_name());
1111+
}
10761112
DTRACE_CLASSINIT_PROBE_WAIT(recursive, -1, wait);
10771113
return;
10781114
}
10791115

10801116
// Step 4
10811117
if (is_initialized()) {
1118+
if (debug_logging_enabled) {
1119+
ResourceMark rm(jt);
1120+
log_debug(class, init)("Thread \"%s\" found %s already initialized",
1121+
jt->name(), external_name());
1122+
}
10821123
DTRACE_CLASSINIT_PROBE_WAIT(concurrent, -1, wait);
10831124
return;
10841125
}
10851126

10861127
// Step 5
10871128
if (is_in_error_state()) {
1129+
if (debug_logging_enabled) {
1130+
ResourceMark rm(jt);
1131+
log_debug(class, init)("Thread \"%s\" found %s is in error state",
1132+
jt->name(), external_name());
1133+
}
10881134
throw_error = true;
10891135
} else {
10901136

10911137
// Step 6
10921138
set_init_state(being_initialized);
10931139
set_init_thread(jt);
1140+
if (debug_logging_enabled) {
1141+
ResourceMark rm(jt);
1142+
log_debug(class, init)("Thread \"%s\" is initializing %s",
1143+
jt->name(), external_name());
1144+
}
10941145
}
10951146
}
10961147

@@ -1564,7 +1615,9 @@ void InstanceKlass::call_class_initializer(TRAPS) {
15641615
LogStream ls(lt);
15651616
ls.print("%d Initializing ", call_class_initializer_counter++);
15661617
name()->print_value_on(&ls);
1567-
ls.print_cr("%s (" PTR_FORMAT ")", h_method() == nullptr ? "(no method)" : "", p2i(this));
1618+
ls.print_cr("%s (" PTR_FORMAT ") by thread \"%s\"",
1619+
h_method() == nullptr ? "(no method)" : "", p2i(this),
1620+
THREAD->name());
15681621
}
15691622
if (h_method() != nullptr) {
15701623
JavaCallArguments args; // No arguments
@@ -4427,4 +4480,3 @@ void ClassHierarchyIterator::next() {
44274480
_current = _current->next_sibling();
44284481
return; // visit next sibling subclass
44294482
}
4430-

src/hotspot/share/oops/instanceKlass.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,14 @@ class InstanceKlass: public Klass {
495495
static void check_prohibited_package(Symbol* class_name,
496496
ClassLoaderData* loader_data,
497497
TRAPS);
498+
499+
JavaThread* init_thread() { return Atomic::load(&_init_thread); }
500+
// We can safely access the name as long as we hold the _init_monitor.
501+
const char* init_thread_name() {
502+
assert(_init_monitor->owned_by_self(), "Must hold _init_monitor here");
503+
return init_thread()->name_raw();
504+
}
505+
498506
public:
499507
// initialization state
500508
bool is_loaded() const { return init_state() >= loaded; }
@@ -504,7 +512,7 @@ class InstanceKlass: public Klass {
504512
bool is_not_initialized() const { return init_state() < being_initialized; }
505513
bool is_being_initialized() const { return init_state() == being_initialized; }
506514
bool is_in_error_state() const { return init_state() == initialization_error; }
507-
bool is_init_thread(JavaThread *thread) { return thread == Atomic::load(&_init_thread); }
515+
bool is_init_thread(JavaThread *thread) { return thread == init_thread(); }
508516
ClassState init_state() const { return Atomic::load(&_init_state); }
509517
const char* init_state_name() const;
510518
bool is_rewritten() const { return _misc_flags.rewritten(); }

src/hotspot/share/runtime/javaThread.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,6 +1588,13 @@ const char* JavaThread::name() const {
15881588
return Thread::name();
15891589
}
15901590

1591+
// Like name() but doesn't include the protection check. This must only be
1592+
// called when it is known to be safe, even though the protection check can't tell
1593+
// that e.g. when this thread is the init_thread() - see instanceKlass.cpp.
1594+
const char* JavaThread::name_raw() const {
1595+
return get_thread_name_string();
1596+
}
1597+
15911598
// Returns a non-null representation of this thread's name, or a suitable
15921599
// descriptive string if there is no set name.
15931600
const char* JavaThread::get_thread_name_string(char* buf, int buflen) const {

src/hotspot/share/runtime/javaThread.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,7 @@ class JavaThread: public Thread {
900900

901901
// Misc. operations
902902
const char* name() const;
903+
const char* name_raw() const;
903904
const char* type_name() const { return "JavaThread"; }
904905
static const char* name_for(oop thread_obj);
905906

0 commit comments

Comments
 (0)