Mattias Nilsson
Mattias Nilsson

Reputation: 3757

Why does the JVM not detect missing method implementation?

We have an application where we publish and interface and an implementation separately. The users will compile against our interface, but only at run-time will they need to deploy the implementation. The implementation is never referred to explicitly.

I got a little curious about what happens if you mix versions of interface and implementation (where newer versions would have for example added methods). So, I made a simple example:

├── mix
│   └── Mix.java
├── v1
│   ├── DummyImpl.java
│   └── DummyInterface.java
└── v2
    ├── DummyImpl.java
    └── DummyInterface.java

v1 of the interface looks like this:

interface DummyInterface {
    void v1();
}

v2 of the interface looks like this:

interface DummyInterface {
    void v1();
    void v2();
}

The Mix.java file looks like this:

class Mix {
    public static void main(String[] args) {
        DummyInterface di = new DummyImpl();
        di.v1();
        if (System.getProperty("foo") != null)
            di.v2();
    }
}

The *Impl classes contain some sort of implementation of the interfaces. What it does is not important. The next step is a bit of trickery.

  1. I compile the files in the v1 directory.
  2. I copy the files from v2 to the mix directory so that I can compile the Mix.java
  3. Running the program works, both with and without the property "foo" set.
  4. I copy the DummyImpl.class from the v1 directory to the mix directory.
  5. I run the program. It works.

The v1 implementation clearly does not fulfill the v2 interface, but the JVM will gladly allow me to run the program.

If I set the "foo" property it will fail, but not until I actually get to that line in the code.

I guess this is where my question comes: Is this guaranteed behavior? If so, where is it specified what will/should happen in this case?

My example is of course silly, but since we have a similar situations in a bigger system, I would like to know what we can count on to work, what wouldn't work and what we can't know if it'll work.

Upvotes: 0

Views: 174

Answers (2)

Powerlord
Powerlord

Reputation: 88796

Because you abstracted the interface, the client program doesn't know that the version running is v1. When it tries calling a v2 method that doesn't exist in v1, you'll end up getting a (not-so) nice NoSuchMethodError.

As a reminder, things marked as errors in Java are considered non-recoverable and you normally shouldn't try to catch it.

Upvotes: 1

UniversE
UniversE

Reputation: 2507

The compiler generates an invokeinterface bytecode for your calls there (not invokespecial). This bytecode does a multistep-lookup for the concrete method to call at runtime. So your code does not fail at compile time.

Upvotes: 4

Related Questions