Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/hotspot/share/oops/instanceKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3702,18 +3702,19 @@ const char* InstanceKlass::init_state_name() const {
return state_names[init_state()];
}

#if !defined(PRODUCT) || INCLUDE_JVMTI
void InstanceKlass::print_class_flags(outputStream* st) const {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incomplete. If the class is an inner class then additional access flags are possible (private, protected, static).
EDIT: Hmm jvm_constants.h does not recognise this either via JVM_RECOGNIZED_CLASS_MODIFIERS. Not sure how this should be handled.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also do we need to handle ACC_MODULE, or do we not actually create an instanceKlass for those?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On jdk side we never have Class for modules. These classfiles are exclusively handled by Java code in ModuleDescriptor I think?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have now changed it to use compute_modifier_flags() instead of access_flags() directly. With this, we get member-class modifiers printed. I expanded the test which shows that private/protected static gets printed. This matches the class' modifiers, which feels like the correct behavior.

ACC_MODULE is not needed here because it never becomes an InstanceKlass. It is rejected as a normal class during parsing.

AccessFlags flags = access_flags();
AccessFlags flags(compute_modifier_flags());
if (flags.is_private ()) st->print("private ");
if (flags.is_protected ()) st->print("protected ");
if (flags.is_public ()) st->print("public ");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: use the same order as for fields and methods.

if (flags.is_static ()) st->print("static ");
if (flags.is_final ()) st->print("final ");
if (flags.is_interface ()) st->print("interface ");
if (flags.is_abstract ()) st->print("abstract ");
if (flags.is_annotation()) st->print("annotation ");
if (flags.is_enum ()) st->print("enum ");
if (flags.is_synthetic ()) st->print("synthetic ");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bit for SYNTHETIC, 0x1000, comes before ANNOTATION, 0x2000, and ENUM, 0x4000. That should be tracked in a separate issue though.

}
#endif // !defined(PRODUCT) || INCLUDE_JVMTI

void InstanceKlass::print_on(outputStream* st) const {
assert(is_klass(), "must be klass");
Expand Down
4 changes: 0 additions & 4 deletions src/hotspot/share/oops/instanceKlass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,11 +1169,7 @@ class InstanceKlass: public Klass {
// Printing
void print_on(outputStream* st) const override;
void print_value_on(outputStream* st) const override;
#if !defined(PRODUCT) || INCLUDE_JVMTI
void print_class_flags(outputStream* st) const;
#else
void print_class_flags(outputStream* st) const PRODUCT_RETURN;
#endif

void oop_print_value_on(oop obj, outputStream* st) override;

Expand Down
28 changes: 13 additions & 15 deletions src/hotspot/share/oops/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2289,23 +2289,21 @@ void Method::print_linkage_flags(outputStream* st) const {
}
#endif //PRODUCT

#if !defined(PRODUCT) || INCLUDE_JVMTI
void Method::print_access_flags(outputStream* st) const {
AccessFlags flags = access_flags();
if (flags.is_public ()) st->print("public ");
if (flags.is_private ()) st->print("private ");
if (flags.is_protected ()) st->print("protected ");
if (flags.is_static ()) st->print("static ");
if (flags.is_final ()) st->print("final ");
if (flags.is_synchronized ()) st->print("synchronized ");
if (flags.is_bridge ()) st->print("bridge ");
if (flags.has_vararg ()) st->print("varargs ");
if (flags.is_native ()) st->print("native ");
if (flags.is_abstract ()) st->print("abstract ");
if (flags.is_strict_method()) st->print("strict ");
if (flags.is_synthetic ()) st->print("synthetic ");
}
#endif // !defined(PRODUCT) || INCLUDE_JVMTI
if (flags.is_public ()) st->print("public ");
if (flags.is_private ()) st->print("private ");
if (flags.is_protected ()) st->print("protected ");
if (flags.is_static ()) st->print("static ");
if (flags.is_final ()) st->print("final ");
if (flags.is_synchronized()) st->print("synchronized ");
if (flags.is_bridge ()) st->print("bridge ");
if (flags.is_varargs ()) st->print("varargs ");
if (flags.is_native ()) st->print("native ");
if (flags.is_abstract ()) st->print("abstract ");
if (flags.is_strictfp ()) st->print("strict ");
if (flags.is_synthetic ()) st->print("synthetic ");
}

void Method::print_value_on(outputStream* st) const {
assert(is_method(), "must be method");
Expand Down
4 changes: 0 additions & 4 deletions src/hotspot/share/oops/method.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -859,11 +859,7 @@ class Method : public Metadata {
void print_on(outputStream* st) const;
#endif
void print_value_on(outputStream* st) const;
#if !defined(PRODUCT) || INCLUDE_JVMTI
void print_access_flags(outputStream* st) const;
#else
void print_access_flags(outputStream* st) const PRODUCT_RETURN;
#endif
void print_linkage_flags(outputStream* st) const PRODUCT_RETURN;

const char* internal_name() const { return "{method}"; }
Expand Down
2 changes: 0 additions & 2 deletions src/hotspot/share/runtime/fieldDescriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ void fieldDescriptor::reinitialize(InstanceKlass* ik, const FieldInfo& fieldinfo
guarantee(_fieldinfo.name_index() != 0 && _fieldinfo.signature_index() != 0, "bad constant pool index for fieldDescriptor");
}

#if !defined(PRODUCT) || INCLUDE_JVMTI
void fieldDescriptor::print_access_flags(outputStream* st) const {
AccessFlags flags = access_flags();
if (flags.is_public ()) st->print("public ");
Expand All @@ -121,7 +120,6 @@ void fieldDescriptor::print_access_flags(outputStream* st) const {
if (flags.is_enum ()) st->print("enum ");
if (flags.is_synthetic()) st->print("synthetic ");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same SYNTHETIC remark here.

}
#endif // !defined(PRODUCT) || INCLUDE_JVMTI

void fieldDescriptor::print_on(outputStream* st) const {
print_access_flags(st);
Expand Down
4 changes: 0 additions & 4 deletions src/hotspot/share/runtime/fieldDescriptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,7 @@ class fieldDescriptor {
void print() const;
void print_on(outputStream* st) const;
void print_on_for(outputStream* st, oop obj);
#if !defined(PRODUCT) || INCLUDE_JVMTI
void print_access_flags(outputStream* st) const;
#else
void print_access_flags(outputStream* st) const PRODUCT_RETURN;
#endif
};

#endif // SHARE_RUNTIME_FIELDDESCRIPTOR_HPP
4 changes: 2 additions & 2 deletions src/hotspot/share/utilities/accessFlags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ class AccessFlags {
bool is_volatile () const { return (_flags & JVM_ACC_VOLATILE ) != 0; }
bool is_bridge () const { return (_flags & JVM_ACC_BRIDGE ) != 0; }
bool is_transient () const { return (_flags & JVM_ACC_TRANSIENT ) != 0; }
bool has_vararg () const { return (_flags & JVM_ACC_VARARGS ) != 0; }
bool is_varargs () const { return (_flags & JVM_ACC_VARARGS ) != 0; }
bool is_native () const { return (_flags & JVM_ACC_NATIVE ) != 0; }
bool is_enum () const { return (_flags & JVM_ACC_ENUM ) != 0; }
bool is_annotation () const { return (_flags & JVM_ACC_ANNOTATION ) != 0; }
bool is_interface () const { return (_flags & JVM_ACC_INTERFACE ) != 0; }
bool is_abstract () const { return (_flags & JVM_ACC_ABSTRACT ) != 0; }
bool is_strict_method() const { return (_flags & JVM_ACC_STRICT ) != 0; }
bool is_strictfp () const { return (_flags & JVM_ACC_STRICT ) != 0; }

// Attribute flags
bool is_synthetic () const { return (_flags & JVM_ACC_SYNTHETIC ) != 0; }
Expand Down
16 changes: 15 additions & 1 deletion test/hotspot/gtest/oops/test_instanceKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,21 @@ TEST_VM(InstanceKlass, class_flag_printer) {
Klass* thread_state_klass = SystemDictionary::resolve_or_fail(thread_state_symbol, true, THREAD);
ASSERT_FALSE(THREAD->has_pending_exception()) << "java/lang/Thread$State must resolve";
InstanceKlass::cast(thread_state_klass)->print_class_flags(&st);
ASSERT_STREQ("public final enum ", st.base());
ASSERT_STREQ("public static final enum ", st.base());

st.reset();
Symbol* certificate_rep_symbol = SymbolTable::new_symbol("java/security/cert/Certificate$CertificateRep");
Klass* certificate_rep_klass = SystemDictionary::resolve_or_fail(certificate_rep_symbol, true, THREAD);
ASSERT_FALSE(THREAD->has_pending_exception()) << "java/security/cert/Certificate$CertificateRep must resolve";
InstanceKlass::cast(certificate_rep_klass)->print_class_flags(&st);
ASSERT_STREQ("protected static ", st.base());

st.reset();
Symbol* arrays_array_list_symbol = SymbolTable::new_symbol("java/util/Arrays$ArrayList");
Klass* arrays_array_list_klass = SystemDictionary::resolve_or_fail(arrays_array_list_symbol, true, THREAD);
ASSERT_FALSE(THREAD->has_pending_exception()) << "java/util/Arrays$ArrayList must resolve";
InstanceKlass::cast(arrays_array_list_klass)->print_class_flags(&st);
ASSERT_STREQ("private static ", st.base());
}

TEST_VM(FieldDescriptor, access_flag_printer) {
Expand Down