3

The compiler for a JVM-based programming language currently that I am working on uses this code to run a specified main method after compilation:

URL url = DyvilCompiler.config.outputDir.toURI().toURL();
Class c = Class.forName(mainType, false, new URLClassLoader(new URL[] { url }, ClassLoader.getSystemClassLoader()));
Method m = c.getMethod("main", String[].class);
m.invoke(null, new Object[] { args });

However, when compiling this code:

package dyvil.test
// some uninteresting import stuff
public class Main
{   
    @ArrayConvertible
    case class IntVector([int] ints = [ 1, 2 ])
    
    public static void main([String] args)
    {
        println(IntVector())
        println([ 1, 2, 3 ] as IntVector)
    }
}

The ClassLoader fails with the inner class (that is actually a nested static class):

java.lang.ClassFormatError: Illegal class name "Ldyvil/test/Main$IntVector;" in class file dyvil/test/Main$IntVector
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at dyvil.test.Main.main(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at dyvil.tools.compiler.util.TestThread.run(TestThread.java:32)

Note that the class files generated for Main dyvil/test/Main and IntVector dyvil/test/Main$IntVector do define the inner class relation:

Inner classes:
    [inner class info: #2 dyvil/test/Main$IntVector, outer class info: #7 dyvil/test/Main
     inner name: #9 IntVector, accessflags: 8 static]
  Enclosing Method: #7  #0 dyvil/test/Main

What is the problem with the Ldyvil/test/Main$IntVector; signature?


Also, when adding the output directory to the classpath and changing the code to

Class c = Class.forName(mainType)

everything works well without any errors.


EDIT: Not only does this cause problems with the JVM, but when using a class like this in Eclipse by importing it, Code Completions stop working completely.

Community
  • 1
  • 1
Clashsoft
  • 11,553
  • 5
  • 40
  • 79
  • 1
    `case class IntVector([int] ints = [ 1, 2 ])` isn't a valid Java statement, as far as I know. Isn't this Scala code? – Laf May 05 '15 at 17:16
  • It's a custom programming language and a custom compiler. – Clashsoft May 05 '15 at 17:22
  • 1
    Oh I see I had missed that part when I first read the question, sorry ;) – Laf May 05 '15 at 17:27
  • Yeah they are quite similar. Also note that although the nested class is not declared `static`, it is still a nested class that doesn't capture the outer one. – Clashsoft May 05 '15 at 17:30
  • Care to post the full javap output of the inner class? The VerifyError message is incomplete in that it doesn't tell us what part of the class file contains the supposedly invalid class name. – Jeffrey Bosboom May 05 '15 at 17:45
  • 2
    At a guess, I think you're using a signature (with 'L' and ';') where just the class name is expected. It is strange that changing class loaders makes a difference, though. – Jeffrey Bosboom May 05 '15 at 17:53
  • 1
    Whoops, looks like I found the error. I was indeed using a signature instead of a class name with a `CHECKCAST` instruction. But it is still interesting that using an URLClassLoader instead of the default one causes this error. – Clashsoft May 05 '15 at 18:47
  • You should add this as answer to your own question. – uraimo Jun 02 '15 at 06:50

0 Answers0