From 9ac3afcf6d8ce69e2f3acc27500fa1803d460492 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Wed, 15 Apr 2026 16:33:39 +0200 Subject: [PATCH 1/3] removed accessflags::print_on and lifted to separate printers --- src/hotspot/share/oops/instanceKlass.cpp | 17 +++- src/hotspot/share/oops/instanceKlass.hpp | 5 + src/hotspot/share/oops/klassVtable.cpp | 6 +- src/hotspot/share/oops/method.cpp | 24 ++++- src/hotspot/share/oops/method.hpp | 7 +- .../share/prims/jvmtiRedefineClasses.cpp | 14 +-- src/hotspot/share/prims/methodHandles.cpp | 4 +- src/hotspot/share/runtime/fieldDescriptor.cpp | 19 +++- src/hotspot/share/runtime/fieldDescriptor.hpp | 7 +- src/hotspot/share/utilities/accessFlags.cpp | 23 +---- src/hotspot/share/utilities/accessFlags.hpp | 14 ++- .../hotspot/gtest/oops/test_instanceKlass.cpp | 98 ++++++++++++++++++- 12 files changed, 186 insertions(+), 52 deletions(-) diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index d675e61cc050f..839247fd150c8 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -3702,13 +3702,26 @@ 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 { + AccessFlags flags = access_flags(); + if (flags.is_public ()) st->print("public "); + 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 "); +} +#endif // !defined(PRODUCT) || INCLUDE_JVMTI + void InstanceKlass::print_on(outputStream* st) const { assert(is_klass(), "must be klass"); Klass::print_on(st); st->print(BULLET"instance size: %d", size_helper()); st->cr(); st->print(BULLET"klass size: %d", size()); st->cr(); - st->print(BULLET"access: "); access_flags().print_on(st); st->cr(); + st->print(BULLET"access: "); print_class_flags(st); st->cr(); st->print(BULLET"flags: "); _misc_flags.print_on(st); st->cr(); st->print(BULLET"state: "); st->print_cr("%s", init_state_name()); st->print(BULLET"name: "); name()->print_value_on(st); st->cr(); @@ -3848,7 +3861,7 @@ void InstanceKlass::print_on(outputStream* st) const { void InstanceKlass::print_value_on(outputStream* st) const { assert(is_klass(), "must be klass"); - if (Verbose || WizardMode) access_flags().print_on(st); + if (Verbose || WizardMode) print_class_flags(st); name()->print_value_on(st); } diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index dd563ad34920e..8c4ecd7d54272 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -1169,6 +1169,11 @@ 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; diff --git a/src/hotspot/share/oops/klassVtable.cpp b/src/hotspot/share/oops/klassVtable.cpp index ead413dfa2c1f..5fefcdfbaaf16 100644 --- a/src/hotspot/share/oops/klassVtable.cpp +++ b/src/hotspot/share/oops/klassVtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1066,7 +1066,7 @@ void klassVtable::dump_vtable() { Method* m = unchecked_method_at(i); if (m != nullptr) { tty->print(" (%5d) ", i); - m->access_flags().print_on(tty); + m->print_access_flags(tty); if (m->is_default_method()) { tty->print("default "); } @@ -1421,7 +1421,7 @@ void klassItable::dump_itable() { Method* m = ime->method(); if (m != nullptr) { tty->print(" (%5d) ", i); - m->access_flags().print_on(tty); + m->print_access_flags(tty); if (m->is_default_method()) { tty->print("default "); } diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 949441585d874..cd8b3cb72ec1b 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -2204,7 +2204,7 @@ void Method::print_on(outputStream* st) const { st->print (" - method holder: "); method_holder()->print_value_on(st); st->cr(); st->print (" - constants: " PTR_FORMAT " ", p2i(constants())); constants()->print_value_on(st); st->cr(); - st->print (" - access: 0x%x ", access_flags().as_method_flags()); access_flags().print_on(st); st->cr(); + st->print (" - access: 0x%x ", access_flags().as_method_flags()); print_access_flags(st); st->cr(); st->print (" - flags: 0x%x ", _flags.as_int()); _flags.print_on(st); st->cr(); st->print (" - name: "); name()->print_value_on(st); st->cr(); st->print (" - signature: "); signature()->print_value_on(st); st->cr(); @@ -2278,8 +2278,8 @@ void Method::print_on(outputStream* st) const { } } -void Method::print_linkage_flags(outputStream* st) { - access_flags().print_on(st); +void Method::print_linkage_flags(outputStream* st) const { + print_access_flags(st); if (is_default_method()) { st->print("default "); } @@ -2289,6 +2289,24 @@ void Method::print_linkage_flags(outputStream* st) { } #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 + void Method::print_value_on(outputStream* st) const { assert(is_method(), "must be method"); st->print("%s", internal_name()); diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index e7479671dcf24..8f03e58d968fa 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -859,7 +859,12 @@ class Method : public Metadata { void print_on(outputStream* st) const; #endif void print_value_on(outputStream* st) const; - void print_linkage_flags(outputStream* st) PRODUCT_RETURN; + #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}"; } diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 8beddc5d406f6..a040812bc73a6 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -4544,7 +4544,7 @@ void VM_RedefineClasses::dump_methods() { LogStreamHandle(Trace, redefine, class, dump) log_stream; Method* m = _old_methods->at(j); log_stream.print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(&log_stream); + m->print_access_flags(&log_stream); log_stream.print(" -- "); m->print_name(&log_stream); log_stream.cr(); @@ -4554,7 +4554,7 @@ void VM_RedefineClasses::dump_methods() { LogStreamHandle(Trace, redefine, class, dump) log_stream; Method* m = _new_methods->at(j); log_stream.print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(&log_stream); + m->print_access_flags(&log_stream); log_stream.print(" -- "); m->print_name(&log_stream); log_stream.cr(); @@ -4564,14 +4564,14 @@ void VM_RedefineClasses::dump_methods() { LogStreamHandle(Trace, redefine, class, dump) log_stream; Method* m = _matching_old_methods[j]; log_stream.print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(&log_stream); + m->print_access_flags(&log_stream); log_stream.print(" -- "); m->print_name(); log_stream.cr(); m = _matching_new_methods[j]; log_stream.print(" (%5d) ", m->vtable_index()); - m->access_flags().print_on(&log_stream); + m->print_access_flags(&log_stream); log_stream.cr(); } log_trace(redefine, class, dump)("_deleted_methods --"); @@ -4579,7 +4579,7 @@ void VM_RedefineClasses::dump_methods() { LogStreamHandle(Trace, redefine, class, dump) log_stream; Method* m = _deleted_methods[j]; log_stream.print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(&log_stream); + m->print_access_flags(&log_stream); log_stream.print(" -- "); m->print_name(&log_stream); log_stream.cr(); @@ -4589,7 +4589,7 @@ void VM_RedefineClasses::dump_methods() { LogStreamHandle(Trace, redefine, class, dump) log_stream; Method* m = _added_methods[j]; log_stream.print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(&log_stream); + m->print_access_flags(&log_stream); log_stream.print(" -- "); m->print_name(&log_stream); log_stream.cr(); diff --git a/src/hotspot/share/prims/methodHandles.cpp b/src/hotspot/share/prims/methodHandles.cpp index 03cb98d8e75b2..99a58b09e7527 100644 --- a/src/hotspot/share/prims/methodHandles.cpp +++ b/src/hotspot/share/prims/methodHandles.cpp @@ -267,7 +267,7 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) { ls.print_cr("memberName: invokeinterface method_holder::method: %s, itableindex: %d, access_flags:", Method::name_and_sig_as_C_string(m->method_holder(), m->name(), m->signature()), vmindex); - m->access_flags().print_on(&ls); + m->print_access_flags(&ls); if (!m->is_abstract()) { if (!m->is_private()) { ls.print("default"); @@ -314,7 +314,7 @@ oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) { ls.print_cr("memberName: invokevirtual method_holder::method: %s, receiver: %s, vtableindex: %d, access_flags:", Method::name_and_sig_as_C_string(m->method_holder(), m->name(), m->signature()), m_klass->internal_name(), vmindex); - m->access_flags().print_on(&ls); + m->print_access_flags(&ls); if (m->is_default_method()) { ls.print("default"); } diff --git a/src/hotspot/share/runtime/fieldDescriptor.cpp b/src/hotspot/share/runtime/fieldDescriptor.cpp index 491157d5bf778..df0c3eb443eb3 100644 --- a/src/hotspot/share/runtime/fieldDescriptor.cpp +++ b/src/hotspot/share/runtime/fieldDescriptor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,8 +108,23 @@ 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 "); + 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_volatile ()) st->print("volatile "); + if (flags.is_transient()) st->print("transient "); + if (flags.is_enum ()) st->print("enum "); + if (flags.is_synthetic()) st->print("synthetic "); +} +#endif // !defined(PRODUCT) || INCLUDE_JVMTI + void fieldDescriptor::print_on(outputStream* st) const { - access_flags().print_on(st); + print_access_flags(st); if (field_flags().is_injected()) st->print("injected "); name()->print_value_on(st); st->print(" "); diff --git a/src/hotspot/share/runtime/fieldDescriptor.hpp b/src/hotspot/share/runtime/fieldDescriptor.hpp index fa3d1b9d23cdc..100f4cb6989c3 100644 --- a/src/hotspot/share/runtime/fieldDescriptor.hpp +++ b/src/hotspot/share/runtime/fieldDescriptor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,6 +111,11 @@ 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 diff --git a/src/hotspot/share/utilities/accessFlags.cpp b/src/hotspot/share/utilities/accessFlags.cpp index ab4c7cde70903..0988da18c5106 100644 --- a/src/hotspot/share/utilities/accessFlags.cpp +++ b/src/hotspot/share/utilities/accessFlags.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,29 +22,8 @@ * */ -#include "oops/oop.inline.hpp" -#include "runtime/atomicAccess.hpp" #include "utilities/accessFlags.hpp" -#if !defined(PRODUCT) || INCLUDE_JVMTI - -void AccessFlags::print_on(outputStream* st) const { - if (is_public ()) st->print("public " ); - if (is_private ()) st->print("private " ); - if (is_protected ()) st->print("protected " ); - if (is_static ()) st->print("static " ); - if (is_final ()) st->print("final " ); - if (is_synchronized()) st->print("synchronized "); - if (is_volatile ()) st->print("volatile " ); - if (is_transient ()) st->print("transient " ); - if (is_native ()) st->print("native " ); - if (is_interface ()) st->print("interface " ); - if (is_abstract ()) st->print("abstract " ); - if (is_synthetic ()) st->print("synthetic " ); -} - -#endif // !PRODUCT || INCLUDE_JVMTI - void accessFlags_init() { assert(sizeof(AccessFlags) == sizeof(u2), "just checking size of flags"); } diff --git a/src/hotspot/share/utilities/accessFlags.hpp b/src/hotspot/share/utilities/accessFlags.hpp index 54bbaeb2c13e1..ee4922e74cc09 100644 --- a/src/hotspot/share/utilities/accessFlags.hpp +++ b/src/hotspot/share/utilities/accessFlags.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,10 +53,15 @@ class AccessFlags { bool is_synchronized() const { return (_flags & JVM_ACC_SYNCHRONIZED) != 0; } bool is_super () const { return (_flags & JVM_ACC_SUPER ) != 0; } 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_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; } // Attribute flags bool is_synthetic () const { return (_flags & JVM_ACC_SYNTHETIC ) != 0; } @@ -92,13 +97,6 @@ class AccessFlags { assert((_flags & JVM_RECOGNIZED_CLASS_MODIFIERS) == _flags, "only recognized flags"); return _flags; } - - // Printing/debugging -#if INCLUDE_JVMTI - void print_on(outputStream* st) const; -#else - void print_on(outputStream* st) const PRODUCT_RETURN; -#endif }; inline AccessFlags accessFlags_from(u2 flags) { diff --git a/test/hotspot/gtest/oops/test_instanceKlass.cpp b/test/hotspot/gtest/oops/test_instanceKlass.cpp index 14fbd7ed53c9d..2f18adee68cd5 100644 --- a/test/hotspot/gtest/oops/test_instanceKlass.cpp +++ b/test/hotspot/gtest/oops/test_instanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/method.hpp" +#include "runtime/fieldDescriptor.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "unittest.hpp" @@ -69,6 +70,65 @@ TEST_VM(InstanceKlass, class_loader_printer) { #endif } +TEST_VM(InstanceKlass, class_flag_printer) { + JavaThread* THREAD = JavaThread::current(); + ThreadInVMfromNative scope(THREAD); + ResourceMark rm; + stringStream st; + + vmClasses::String_klass()->print_class_flags(&st); + ASSERT_STREQ("public final ", st.base()); + + st.reset(); + vmClasses::Runnable_klass()->print_class_flags(&st); + ASSERT_STREQ("public interface abstract ", st.base()); + + st.reset(); + Symbol* override_symbol = SymbolTable::new_symbol("java/lang/Override"); + Klass* override_klass = SystemDictionary::resolve_or_fail(override_symbol, true, THREAD); + ASSERT_FALSE(THREAD->has_pending_exception()) << "java/lang/Override must resolve"; + InstanceKlass::cast(override_klass)->print_class_flags(&st); + ASSERT_STREQ("public interface abstract annotation ", st.base()); + + st.reset(); + Symbol* thread_state_symbol = SymbolTable::new_symbol("java/lang/Thread$State"); + 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()); +} + +TEST_VM(FieldDescriptor, access_flag_printer) { + JavaThread* THREAD = JavaThread::current(); + ThreadInVMfromNative scope(THREAD); + ResourceMark rm; + stringStream st; + + InstanceKlass* integer_klass = vmClasses::Integer_klass(); + Symbol* min_value_symbol = SymbolTable::new_symbol("MIN_VALUE"); + + fieldDescriptor fd; + ASSERT_TRUE(integer_klass->find_local_field(min_value_symbol, vmSymbols::int_signature(), &fd)) + << "Integer.MIN_VALUE must exist"; + fd.print_on(&st); + ASSERT_THAT(st.base(), HasSubstr("public static final 'MIN_VALUE' 'I'")) << "Must print field access flags"; + + st.reset(); + Symbol* thread_state_symbol = SymbolTable::new_symbol("java/lang/Thread$State"); + 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"; + + fieldDescriptor enum_fd; + Symbol* enum_symbol = SymbolTable::new_symbol("NEW"); + Symbol* enum_signature = SymbolTable::new_symbol("Ljava/lang/Thread$State;"); + ASSERT_TRUE(InstanceKlass::cast(thread_state_klass)->find_local_field(enum_symbol, enum_signature, &enum_fd)) + << "Thread.State.NEW must exist"; + + enum_fd.print_on(&st); + ASSERT_THAT(st.base(), HasSubstr("public static final enum 'NEW' 'Ljava/lang/Thread$State;'")) + << "Must print enum field access flags"; +} + #ifndef PRODUCT // This class is friends with Method. class MethodTest : public ::testing::Test{ @@ -85,4 +145,40 @@ TEST_VM(Method, method_name) { ASSERT_TRUE(method != nullptr) << "Object must have toString"; MethodTest::compare_names(method, tostring); } + +TEST_VM(Method, access_flag_printer) { + ThreadInVMfromNative scope(JavaThread::current()); + ResourceMark rm; + stringStream st; + + InstanceKlass* object_klass = vmClasses::Object_klass(); + Symbol* wait_symbol = SymbolTable::new_symbol("wait"); + Method* wait_method = object_klass->find_method(wait_symbol, vmSymbols::long_void_signature()); + ASSERT_TRUE(wait_method != nullptr) << "Object must have wait(long)"; + wait_method->print_access_flags(&st); + ASSERT_STREQ("public final ", st.base()); + + st.reset(); + Symbol* symbol_hash_code = SymbolTable::new_symbol("hashCode"); + Method* hash_code = object_klass->find_method(symbol_hash_code, vmSymbols::void_int_signature()); + ASSERT_TRUE(hash_code != nullptr) << "Object must have hashCode()"; + hash_code->print_access_flags(&st); + ASSERT_STREQ("public native ", st.base()); + + st.reset(); + InstanceKlass* string_klass = vmClasses::String_klass(); + Symbol* format_symbol = SymbolTable::new_symbol("format"); + Symbol* format_signature = SymbolTable::new_symbol("(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;"); + Method* format_method = string_klass->find_method(format_symbol, format_signature); + ASSERT_TRUE(format_method != nullptr) << "String must have format(String, Object...)"; + format_method->print_access_flags(&st); + ASSERT_STREQ("public static varargs ", st.base()); + + st.reset(); + Symbol* compare_to_symbol = SymbolTable::new_symbol("compareTo"); + Method* compare_to_bridge_method = string_klass->find_method(compare_to_symbol, vmSymbols::object_int_signature()); + ASSERT_TRUE(compare_to_bridge_method != nullptr) << "String must have bridge compareTo(Object)"; + compare_to_bridge_method->print_access_flags(&st); + ASSERT_STREQ("public bridge synthetic ", st.base()); +} #endif From f471984f046372f36d7f91b09a9ff4b21b9ac86a Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Thu, 16 Apr 2026 14:22:49 +0200 Subject: [PATCH 2/3] feedback fixes --- src/hotspot/share/oops/instanceKlass.cpp | 7 +++-- src/hotspot/share/oops/instanceKlass.hpp | 4 --- src/hotspot/share/oops/method.cpp | 28 +++++++++---------- src/hotspot/share/oops/method.hpp | 4 --- src/hotspot/share/runtime/fieldDescriptor.cpp | 2 -- src/hotspot/share/runtime/fieldDescriptor.hpp | 4 --- src/hotspot/share/utilities/accessFlags.hpp | 4 +-- .../hotspot/gtest/oops/test_instanceKlass.cpp | 16 ++++++++++- 8 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 839247fd150c8..5bf0fd0aeb94f 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -3702,10 +3702,12 @@ 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 { - 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 "); + 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 "); @@ -3713,7 +3715,6 @@ void InstanceKlass::print_class_flags(outputStream* st) const { if (flags.is_enum ()) st->print("enum "); if (flags.is_synthetic ()) st->print("synthetic "); } -#endif // !defined(PRODUCT) || INCLUDE_JVMTI void InstanceKlass::print_on(outputStream* st) const { assert(is_klass(), "must be klass"); diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 8c4ecd7d54272..205bc41a37823 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -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; diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index cd8b3cb72ec1b..1e3374edfed93 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -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"); diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index 8f03e58d968fa..cf620fcfcee78 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -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}"; } diff --git a/src/hotspot/share/runtime/fieldDescriptor.cpp b/src/hotspot/share/runtime/fieldDescriptor.cpp index df0c3eb443eb3..4ad916cfff7d3 100644 --- a/src/hotspot/share/runtime/fieldDescriptor.cpp +++ b/src/hotspot/share/runtime/fieldDescriptor.cpp @@ -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 "); @@ -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 "); } -#endif // !defined(PRODUCT) || INCLUDE_JVMTI void fieldDescriptor::print_on(outputStream* st) const { print_access_flags(st); diff --git a/src/hotspot/share/runtime/fieldDescriptor.hpp b/src/hotspot/share/runtime/fieldDescriptor.hpp index 100f4cb6989c3..1b423377cc217 100644 --- a/src/hotspot/share/runtime/fieldDescriptor.hpp +++ b/src/hotspot/share/runtime/fieldDescriptor.hpp @@ -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 diff --git a/src/hotspot/share/utilities/accessFlags.hpp b/src/hotspot/share/utilities/accessFlags.hpp index ee4922e74cc09..a0aef9daa0c01 100644 --- a/src/hotspot/share/utilities/accessFlags.hpp +++ b/src/hotspot/share/utilities/accessFlags.hpp @@ -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; } diff --git a/test/hotspot/gtest/oops/test_instanceKlass.cpp b/test/hotspot/gtest/oops/test_instanceKlass.cpp index 2f18adee68cd5..ac489b786fdc0 100644 --- a/test/hotspot/gtest/oops/test_instanceKlass.cpp +++ b/test/hotspot/gtest/oops/test_instanceKlass.cpp @@ -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) { From 71b7c76ef73afbf0bee073dd01f5a13475953ffb Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Fri, 17 Apr 2026 11:32:07 +0200 Subject: [PATCH 3/3] reorder private/public/protected in instanceklass --- src/hotspot/share/oops/instanceKlass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 5bf0fd0aeb94f..c8696397fb1bd 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -3704,9 +3704,9 @@ const char* InstanceKlass::init_state_name() const { void InstanceKlass::print_class_flags(outputStream* st) const { AccessFlags flags(compute_modifier_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_public ()) st->print("public "); if (flags.is_static ()) st->print("static "); if (flags.is_final ()) st->print("final "); if (flags.is_interface ()) st->print("interface ");