FULL PRODUCT VERSION :
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) Client VM (build 14.0-b16, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
Invoking a public final method on a package local abstract class through a concrete implementing class results in an Exception similar to the following
can not access a member of class AbstractImpl with modifiers "public final".
However, removing the final modifier on the method results in a correct calling behaviour and the method may be called by reflection as expected.
I understand that this behaviour might result from the way java links virtual vs. final methods but nevertheless.
Shouldn't it be accessible in both ways? Calling on a concrecte object without reflection ofc works, too.
I have to break my class design to get this code running, and remove the final modifier and put it into the concrete class which is annoying.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
given the following:
package a;
class AbstractImpl {
public final void final_method() {
// do something
}
public void not_final() {
// do something
}
}
package a;
public class ConcrecteImpl extends AbstractImpl {
}
package b;
public static void main(String args[]) {
ConcreteImpl p = new ConcreteImpl();
// will work
p.final_method();
p.not_final() ;
Method not_final_method = obj.getClass().getMethod( "not_final_method", EMPTY_PARAMETERS );
// will work
not_final_method.invoke(p, EMPTY_PARAMETERS);
Method final_method = obj.getClass().getMethod( "final_method", EMPTY_PARAMETERS );
// wont work, crashes with illegalAccessException, can not access with modifier public final
final_method.invoke(p, EMPTY_PARAMETERS);
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would expect that both methods could be called by reflection as they are when calling them through an object.
ACTUAL -
Only the method without the final modifier can be called.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.IllegalAccessException: Class Test can not access a member of class a.AbstractImpl with modifiers "public final"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
at java.lang.reflect.Method.invoke(Method.java:588)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package a;
abstract class AbstractImpl {
public final void final_method() {
// do something
}
public void not_final() {
// do something
}
}
package a;
public class ConcrecteImpl extends AbstractImpl {
}
package b;
import a.*;
public class Test {
public static void main(String args[]) {
ConcreteImpl p = new ConcreteImpl();
// will work
p.final_method();
p.not_final() ;
Method not_final_method = obj.getClass().getMethod( "not_final_method", EMPTY_PARAMETERS );
not_final_method.invoke(p, EMPTY_PARAMETERS);
Method final_method = obj.getClass().getMethod( "final_method", EMPTY_PARAMETERS );
// wont work, crashes with illegalAccessException, can not access with modifier public final
final_method.invoke(p, EMPTY_PARAMETERS);
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Remove the final modifier on the implementation of the method in the abstract class