From 0385975f44fbe9d199677754ff5006bc5784b9c5 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 22 Jul 2025 00:39:01 +0000 Subject: [PATCH] 8356941: AbstractMethodError in HotSpot Due to Incorrect Handling of Private Method Reviewed-by: coleenp, heidinga --- src/hotspot/share/classfile/defaultMethods.cpp | 8 +++----- .../vmTestbase/vm/runtime/defmeth/PrivateMethodsTest.java | 8 +++++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/classfile/defaultMethods.cpp b/src/hotspot/share/classfile/defaultMethods.cpp index a9c694c33c1..f84c3b65f5f 100644 --- a/src/hotspot/share/classfile/defaultMethods.cpp +++ b/src/hotspot/share/classfile/defaultMethods.cpp @@ -658,13 +658,11 @@ static void find_empty_vtable_slots(GrowableArray* slots, if (super->default_methods() != nullptr) { for (int i = 0; i < super->default_methods()->length(); ++i) { Method* m = super->default_methods()->at(i); - // m is a method that would have been a miranda if not for the - // default method processing that occurred on behalf of our superclass, - // so it's a method we want to re-examine in this new context. That is, - // unless we have a real implementation of it in the current class. if (!already_in_vtable_slots(slots, m)) { + // m is a method that we need to re-examine, unless we have a valid concrete + // implementation in the current class - see FindMethodsByErasedSig::visit. Method* impl = klass->lookup_method(m->name(), m->signature()); - if (impl == nullptr || impl->is_overpass() || impl->is_static()) { + if (impl == nullptr || impl->is_overpass() || impl->is_static() || impl->is_private()) { slots->append(new EmptyVtableSlot(m)); } } diff --git a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/PrivateMethodsTest.java b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/PrivateMethodsTest.java index 8f204cc13cd..243ce82c9d8 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/PrivateMethodsTest.java +++ b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/PrivateMethodsTest.java @@ -680,6 +680,8 @@ public class PrivateMethodsTest extends DefMethTest { * public class C extends B { } * * TEST: { B b = new C(); b.m()I throws IllegalAccessError; } + * TEST: { I b = new B(); b.m()I returns 3; } + * TEST: { I c = new C(); c.m()I returns 3; } */ public void testPrivateSuperClassMethodDefaultMethodNoOverride(TestBuilder b) { ConcreteClass A = b.clazz("A") @@ -694,6 +696,10 @@ public class PrivateMethodsTest extends DefMethTest { ConcreteClass C = b.clazz("C").extend(B).build(); - b.test().privateCallSite(B, C, "m", "()I").throws_(IllegalAccessError.class).done(); + b.test().privateCallSite(B, C, "m", "()I").throws_(IllegalAccessError.class).done() + .test(). callSite(I, B, "m", "()I").returns(3).done() + .test(). callSite(I, C, "m", "()I").returns(3).done() + ; + } }