There are two valid methods that can be called for b.method(b);:
final int method(A a) { return 4 + super.method(a); }
static int method(B b) { return 2 + b.method((A)b); } // inherited from A
The compiler chooses the more specific one - method(B). It doesn't matter that it is static. Static methods can be called on an instance too. See also: Is calling static methods via an object "bad form"? Why?
Now we need to resolve b.method((A)b);. b's compile time type is A so the compiler only searches in A. The argument expression's compile type is also A. The only applicable method is:
int method(A a) { return 1; }
At runtime, b is found to be an instance of B, so the overridden method in B is called instead:
final int method(A a) { return 4 + super.method(a); }
Now we resolve super.method(a);. The types involved here are exactly the same as those in b.method((A)b);, but we are using super, so the implementation in the superclass of B, i.e. in A, is called instead:
int method(A a) { return 1; }
For b.method(c);, the argument's compile time type is C, so we have three applicable methods:
final int method(A a) { return 4 + super.method(a); }
static int method(B b) { return 2 + b.method((A)b); } // inherited from A
int method(C c) { return 8 + this.method((B)c); }
Again, the most specific, method(C) is chosen.
Then we resolve this.method((B)c);. This is resolved in exactly the same way as b.method(b);. The compile-time types are the same. The fact that the runtime type of the parameter is a C object doesn't really matter, because all C overrides is the method(C) method, which we never called when resolving b.method(b);.