Java 8 bytecode how are default methods in interfaces marked

osanger :

since Java 8 it is allowed to predefine methods in interfaces. Some of these standard implementations are already implemented on the "standard" interfaces such as CharSequence. If you try to read Java 8 ByteCode (e.g. the rt.jar of the Java home folder) with a JVM 7, an error occurs.

e.g. the type java.lang.CharSequence cannot be resolved.

This may not be the only difference between levels, but I would like to understand the structure of the new byte code.

public interface com.company.ITest {
public void HelloWorld();
Code:
   0: getstatic     #1                  // Field java/lang/System.out:Ljava/io/PrintStream;
   3: ldc           #2                  // String hello world
   5: invokevirtual #3                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8: return
}

This Bbytecode was produced by this Javacode:

public interface ITest {
    default void HelloWorld(){
        System.out.println("hello world");
    }
}

So here is my question: How does an default interface impact on the constant pool?

Is any of these flags relevant:

CONSTANT_MethodHandle CONSTANT_MethodType CONSTANT_InvokeDynamic

Holger :

It depends on what you are actually doing, which obstacle you will stumble upon. You say

If you try to read Java 8 ByteCode (e.g. the rt.jar of the Java home folder) with a JVM 7, an error occurs.

e.g. the type java.lang.CharSequence cannot be resolved.

but this doesn’t even remotely match what will happen when you try to “read Java 8 ByteCode with a JVM 7”. If you try to load a Java 8 class with a Java 7 JVM, you usually get a VerifyError with a message telling you that the class file version is not supported.

Instead, the error message looks very much like the well known error message of the Eclipse compiler when it fails at reading the byte code of a class file, which has nothing to do with the JVM. As explained in this answer, Eclipse doesn’t seem to make a difference between classes it didn’t find or classes it failed to parse, just saying “cannot be resolved”. It also seems to ignore the class file version number, so it happens to work with newer class files when they are not using newer features like default methods.

On a technical level, the differences are tiny. There is no relationship between default methods and the constant pool. The pool entry types CONSTANT_MethodHandle, CONSTANT_MethodType, and CONSTANT_InvokeDynamic are not related to default methods and they are not even new—they are already part of the standard since Java 7 (which doesn’t stop some tool vendors from ignoring them as long as they do not encounter them). A default method simply is a method which is not abstract and not static, just like an ordinary public instance method, but in an interface. The new thing is that this is allowed now. A simple class file parser which doesn’t care whether it is reading a class or interface would have no difficulties with that. But depending on what the tool does with the data, it may struggle with such a class file (if it didn’t already stop at the version number), like older Eclipse compilers do.

If a JVM’s verifier didn’t already stop at the version number, it would simply throw a different VerifierError saying the the class file violates the constraint that all methods must be abstract.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=469104&siteId=1