As the Java programming language and the JVM specification evolved in time, the need arose to make ol d and new bugs and features live together in harmony. Resulting from efforts to solve this recurring issue, a number of exotic, and often ill-documented entities appeared from time to time, puzzling whoever wants to, or needs to, delve in the gory details of what happens behind the scene when a piece of Java software is run. In this article I will discuss three kind of these entities, namely, mirandas, bridges and overpasses. These are artificially generated methods aimed at handling some situations that arise when linking and invoking other, user-defined methods. I will refer mostly to Java (and OpenJDK) 8.
Let us start with miranda methods. The Miranda warning states, among the other things, that if you cannot afford a lawyer, one will be appointed to you. Similarly, a miranda method is a method for which the language runtime provides a default definition to all classes that do not define it on their own. For example, the E programming language has a so-called miranda protocol made of a set of methods that all the objects receive together with a default implementation. For what concerns OpenJDK the motivation for miranda methods is quite different. Long before Hotspot there was the Sun JVM. The 1.1 version had a bug — when deciding whether a class declares a method, the Sun JVM walked the superclass hierarchy, but not the superinterface hierarchy. What were the consequences? Let us suppose that we have the following interface:
would be problematic. I did not have the opportunity to experiment with the JDK 1.1 but I reckon that this would happen: When javac would compile the statement b.a(); of the Main.main(String) method, it would determine that the variableb has (static) type B and therefore would emit the bytecode instruction invokevirtual B.a()V. When executing this bytecode, the Sun JVM would try and resolve the symbolic reference B.a()V, but because of the bug it would erroneously conclude that B has no a() method, therefore failing. To rescue the situation, the javac compiler can be instructed to emit miranda declarations for the abstract methods that a class inherits from a superinterface, and that the class (or one of its superclasses) does not redeclare or implement. By default current version 8javac implementations do not emit miranda methods, thus if you javac B.java the resulting Java 8 class will have this shape: