Q:

what happens in a java jvm executing legacy code, which was invalidated by a language change

Suppose you have legacy java code which can not be compiled by an up-to-date version of java. e.g.
public class ProviderUnavailableException extends Exception {

    private int cause;

    public int getCause(){
        return cause;
    }
    // rest of implementation
}

Back at the time of Java 1.3 this code was valid. 
In Java 1.4 the class Throwable 'redefined' the method getCause(). It looks like this:
public Throwable getCause()

Now the legacy code is invalid (because 'int' is not a subtype of 'Throwable') but does not lead to runtime problems. Or can this happen under some circumstances?
Is it correct that back a the compile time, the compiler had generated the byte code to handle the execution of the method getCause solely in that class and therefore 'knows' that no super class has to be invoked?
EDIT
i checked the byte code of the legacy code with "javap -c". 
  public int getCause();
    Code: 
     0: aload_0
     1: getfield #2; //Field _cause:I
     4: ireturn 

So it's returning the local field. Seems ok for me. 

A:

In bytecode the method is referred to by its name, parameter types and return type. So the two methods are quite separate.
In the bytecode notation, your 1.3 method would be (I think):
getCause()J

While the new 1.4 method is:
getCause()Ljava/lang/Throwable;

You can see the signatures using javap -s.
Covariant return types are actually implemented at compile time by javac using synthetic bridge methods. They do not have runtime support. So if you override Object run() with String run() javac will create both methods in the derived class with Object run() calling String run().

