Menu

#413 Problem with loading of inner classes that implement an interface

accepted
nobody
OpenJML
5
2015-05-22
2015-05-06
No

There seems to be a problem with the OpenJML runtime assertion checker related to loading of inner classes that implement an interface. It can easily be shown using the small program given below.

interface X
{
    X m();
}

public class Main
{
    public static void main(String[] args)
    {
        // Do something that forces the inner class to be loaded
        new C();
        System.out.println("Done!");
    }

    public static class C implements X
    {
        @Override
        public C m()
        {
            return null;
        }
    }
}

If you run the main method using the runtime assertion checker the program produces the following error.

Exception in thread "main" java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file Main$C
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at Main.main(Main.java:11)

I was able to produce it using both the Eclipse plugin as well as the command-line version of the runtime assertion checker on a 64 bit Ubuntu Gnome machine.

I played around with it a bit and the problem seems to be that the inner class implements the interface method using a return type that is "narrower" than that originally specified in the interface. According to the stack trace this seems to mess up the loading of the class. Note that implementing interfaces like this is perfectly legal in Java and it executes without any problems on an regular JVM.

However, the problem does NOT occur if you change the return type in the inner class to be X, i.e. public X m()

In some of my work its quite important for me to be able to implement interfaces like this. A workaround is to make the inner class an outer class but I would really like to avoid this.

Thanks in advance.

Discussion

  • David Cok

    David Cok - 2015-05-22
    • labels: bug --> bug, OpenJML
    • status: open --> accepted
     
  • David Cok

    David Cok - 2015-05-22

    Problem reproduced and under investigation.

     

Log in to post a comment.