# Thursday, October 17, 2013
« Type Confusion PoC for CVE-2013-3131 (MS... | Main | Java Method Overriding Is FUBAR Part 8 o... »
Java Method Overriding Is FUBAR Part 7 of ∞

My friends at Oracle seem determined to make me finish my infinite series of blog posts of Java method overriding.

Before the 7u45 security update the following (pseudo) code ran fine:

class A {
  final void m() { }

class B extends A {
  private void m() { }

Now with 7u45, loading class B throws an exception:

java.lang.VerifyError: class B overrides final method m.()V

This makes no sense at all and is a misguided attempt to fix the issue I reported here. Ironically, it doesn't even completely fix the issue, because a static finalize method still prevents the final finalizer from running:

class A {
  protected void finalize() {

class B extends A {
  public static void main(String[] args) {
    new B();

  private static void finalize() { }

Pre-emptive comment about comments: Feel free to leave comments, but I'm not going to respond to people that clearly don't have a clue.

Update: I misread the spec. The change is actually in line with the spec. Unfortunately the spec is wrong.

Thursday, October 17, 2013 9:33:48 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [8]
Thursday, October 17, 2013 11:33:24 PM (W. Europe Daylight Time, UTC+02:00)
Well, your method is not final in the second example?
Friday, October 18, 2013 9:39:28 AM (W. Europe Daylight Time, UTC+02:00)
I assume that the pseudo-code represents a patched class file, as this code definitely wouldn't compile (JLS,

As for the VerifyError: The link you provided (JVMS-5.4.5) clearifies, that the method B.m() indeed overwrites A.m(). And in chapter 4.10 of the JVMS (Verification of class Files), it is defined that the check 'Ensuring that final classes are not subclassed and that final methods are not overridden (§5.4.5).' must be performed.

Therefore I argue that the current behaviour (as of 7u45) is correct.
Wednesday, October 23, 2013 2:59:36 PM (W. Europe Daylight Time, UTC+02:00)
@Michael, B.m is not trying overriding it, but merely trying to create a private method local to B. Right?
Wednesday, October 23, 2013 5:33:43 PM (W. Europe Daylight Time, UTC+02:00)
@Joe Correct. Private methods don't participate in method overriding in any way. That has always been the case. I don't know how to argue with people who read JVMS-5.4.5 as saying otherwise, they seem to live in an alternate reality where words mean different things.
Monday, October 28, 2013 3:24:51 PM (W. Europe Standard Time, UTC+01:00)
@Jeroen: Can you provide any information as where in the JVMS it defines, that private methods do not participate in the method overriding check? I clearly cannot see why JVMS-5.4.5 would say so:

* B is a subclass of A -> TRUE
* m2 (which refers to A.m) has the same name and descriptor as m1 (B.m) -> TRUE
* m2 (which refers to A.m) is marked ACC_PUBLIC; or is marked ACC_PROTECTED; or is marked neither ACC_PUBLIC nor ACC_PROTECTED nor ACC_PRIVATE and belongs to the same run-time package as B -> TRUE, its package protected

Monday, October 28, 2013 3:54:45 PM (W. Europe Standard Time, UTC+01:00)
The last bullet point you quoted says that B.m2 must be ACC_PUBLIC or ACC_PROTECTED or package accessible and in the same package to override A.m.

Note that this text is very new in the JVM spec, before Java 7 there was nothing the JVMS about method overriding, so for many years people have implemented JVMs by copying the behavior of the reference implementation, which has *never* considered private methods in its overriding algorithm.

The reason the wrong finalize method is called has nothing to do with overriding, it's just the consequence of the incorrect usage of reflection in the native code.
Monday, October 28, 2013 4:30:00 PM (W. Europe Standard Time, UTC+01:00)
@Jeroen: I think I see our misunderstanding. The JVMS defines m2 as the method in the super-class which will be overridden and m1 as the method in the sub-class that will override it. So m1 will override m2 and not the other way around.

The last bullet point that I quoted says that A.m must be ACC_PUBLIC or ACC_PROTECTED or package accessible and in the same package to allow B.m to override it. It does not imply any access modifiers for B.m.

The finalize call seems to be a different problem and was not what I was referring to. I did _not_ try to argue that a private static method will override a protected instance method.
Monday, October 28, 2013 5:21:04 PM (W. Europe Standard Time, UTC+01:00)
Yes, you are correct. I misread the spec. This however changes nothing in my opinion, just that the spec is incorrect.

I do however think I now have a better understanding of how this went wrong. With Java 7 the spec finally got the 5.4.5 section that specifies method overriding, but there was a mistake (it considered private methods as candidates for overriding). Then someone noticed the behavior was out of line with the spec and the behavior was "corrected", instead of the spec.

I'd be willing to entertain the idea that I'm wrong, if it weren't for the fact that the JVM implementation is such a mess (and the spec is unclear too, not to mention that it has always lacked any proper description of how method overriding works).
Comments are closed.