Search code examples
javajvmidentifierjlsverifyerror

Identifiers in angle brackets on the JVM causing Internal Method error


The following code uses a method with the name <traitinit>, but is rejected by the JVM with a VerifyError:

class Foo
{
    static void `<traitinit>`() // pseudocode identifier, not possible in Java
    {
    }

    static void test()
    {
        `<traitinit>`() // call the <traitinit> method
    }
}

The error:

java.lang.VerifyError: Illegal call to internal method
 Exception Details:
  Location:
    foo/bar/Foo.test()V @5: invokestatic
  Reason:
    Error exists in the bytecode

Since the JVM already uses <init> and <clinit> for constructors and class initializers, this seems like a reasonable error message. However, is there any section in the JVM Specification that clearly defines what an internal method is? I would have guessed that it only reserves the two particular identifiers from above, but that doesn't seem to be the case.


Solution

  • I found the relevant section (§4.2.2. Unqualified Names) of the JVM Specification myself:

    4.2.2. Unqualified Names

    Names of methods, fields, local variables, and formal parameters are stored as unqualified names. An unqualified name must contain at least one Unicode code point and must not contain any of the ASCII characters . ; [ / (that is, period or semicolon or left square bracket or forward slash).

    Method names are further constrained so that, with the exception of the special method names <init> and <clinit> (§2.9), they must not contain the ASCII characters < or > (that is, left angle bracket or right angle bracket).

    (emphasis mine)