groovy
  1. groovy
  2. GROOVY-4020

java.lang.ClassFormatError when using the name including "-" sign

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.6.5
    • Fix Version/s: None
    • Component/s: Compiler
    • Labels:
      None
    • Number of attachments :
      0

      Description

      I'm not sure if there any constraint with the name parameter before passing to GroovyCodeSource but it is raising an exception if the name includes "-" sign :

      GroovyCodeSource gcs = new GroovyCodeSource(inputStream, "file-name.gtmpl", "/groovy/shell");

      Here is the exception :

      Caused by: java.lang.ClassFormatError: Illegal class name "File-name" in class file File-name
      at java.lang.ClassLoader.defineClass1(Native Method)
      at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
      at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
      at groovy.lang.GroovyClassLoader.access$200(GroovyClassLoader.java:54)
      at groovy.lang.GroovyClassLoader$ClassCollector.createClass(GroovyClassLoader.java:482)
      at groovy.lang.GroovyClassLoader$ClassCollector.onClassNode(GroovyClassLoader.java:499)
      at groovy.lang.GroovyClassLoader$ClassCollector.call(GroovyClassLoader.java:503)
      at org.codehaus.groovy.control.CompilationUnit$10.call(CompilationUnit.java:728)
      at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:925)
      at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:462)
      at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:278)

      It seems that the name parameter is used for createing Class in Java, so it must be a binary name as defined by the Java Language Specification. If so, the name would be validated and converted to good one ? Or I must to take care of that myself before using GroovyCodeSource ?

        Activity

        Hide
        Roshan Dawrani added a comment -

        Yes, the name that you pass to GroovyCodeSource is used to come up with the class name of the script class that you parse using that GroovyCodeSource.

        The behavior reported (class loader rejecting such classes with invalid names with ClassFormatError) seems to be JVM specific.

        I am on Windows XP with following Java 1.5.0_04 and for me the class loading does not fail.

        Should we validate the class names and reject the invalid ones?

        Show
        Roshan Dawrani added a comment - Yes, the name that you pass to GroovyCodeSource is used to come up with the class name of the script class that you parse using that GroovyCodeSource. The behavior reported (class loader rejecting such classes with invalid names with ClassFormatError) seems to be JVM specific. I am on Windows XP with following Java 1.5.0_04 and for me the class loading does not fail. Should we validate the class names and reject the invalid ones?
        Hide
        Tran The Trong added a comment -

        a validation is needed i think.

        if the class name is wrong, is there any reason to keep you to automatically convert it to good one ?

        Show
        Tran The Trong added a comment - a validation is needed i think. if the class name is wrong, is there any reason to keep you to automatically convert it to good one ?
        Hide
        Roshan Dawrani added a comment -

        Jochen, what do you think? Can we reject the invalid class names or convert them into good ones?

        I think I have seen at least one place in groovy where invalid class names are converted.

        Show
        Roshan Dawrani added a comment - Jochen, what do you think? Can we reject the invalid class names or convert them into good ones? I think I have seen at least one place in groovy where invalid class names are converted.
        Hide
        blackdrag blackdrag added a comment -

        if we convert the question is to what.

        Show
        blackdrag blackdrag added a comment - if we convert the question is to what.
        Hide
        Tran The Trong added a comment -

        does the GROOVY-3054 relate to this problem ?

        Show
        Tran The Trong added a comment - does the GROOVY-3054 relate to this problem ?
        Hide
        Roshan Dawrani added a comment -

        Not really.

        GROOVY-3054 seems more about extracting just the file name part from the whole path of the script file. So, if you have c:/groovy/MyScript.groovy, it removes "c:/groovy/" from the front and ".groovy" from the end and comes up with MyScript as the class name. It, kind-of, assumes that file name portion itself will be a valid one, and not like "file-name.gtmpl" - that is the portion that needs to be fixed now.

        Show
        Roshan Dawrani added a comment - Not really. GROOVY-3054 seems more about extracting just the file name part from the whole path of the script file. So, if you have c:/groovy/MyScript.groovy, it removes "c:/groovy/" from the front and ".groovy" from the end and comes up with MyScript as the class name. It, kind-of, assumes that file name portion itself will be a valid one, and not like "file-name.gtmpl" - that is the portion that needs to be fixed now.
        Hide
        Nicolas RAOUL added a comment -

        I can confirm this on Ubuntu 2011.04 with bash and Groovy 1.7.4 JVM: 1.6.0_22:

        $ groovy xmlslurper-url-bug.groovy
        Caught: java.lang.ClassFormatError: Illegal class name "xmlslurper-url-bug" in class file xmlslurper-url-bug
        $ mv xmlslurper-url-bug.groovy xmlslurperurlbug.groovy
        $ groovy xmlslurperurlbug.groovy
        Hello World

        Show
        Nicolas RAOUL added a comment - I can confirm this on Ubuntu 2011.04 with bash and Groovy 1.7.4 JVM: 1.6.0_22: $ groovy xmlslurper-url-bug.groovy Caught: java.lang.ClassFormatError: Illegal class name "xmlslurper-url-bug" in class file xmlslurper-url-bug $ mv xmlslurper-url-bug.groovy xmlslurperurlbug.groovy $ groovy xmlslurperurlbug.groovy Hello World
        Hide
        Aaron J. Garcia added a comment -

        I'm having this exact same issue. I'm trying to make a Groovy CGI Script, and I want to call it "test-groovy.cgi". I have to do one of two things:

        1) Make a class definition inside of test-groovy.cgi with a good name like TestGroovy, and a main method.
        2) Rename my file to testGroovy.cgi.

        I think a good solution would be to just remove the "-" from the file name when creating the generated class name.

        Show
        Aaron J. Garcia added a comment - I'm having this exact same issue. I'm trying to make a Groovy CGI Script, and I want to call it "test-groovy.cgi". I have to do one of two things: 1) Make a class definition inside of test-groovy.cgi with a good name like TestGroovy, and a main method. 2) Rename my file to testGroovy.cgi. I think a good solution would be to just remove the "-" from the file name when creating the generated class name.
        Hide
        Paul King added a comment -

        I think Roshan's suggestion of reusing org.codehaus.groovy.bsf.GroovyEngine#convertToValidJavaClassname() is the way to go. This would not remove characters like '-' but instead replace them with '_'. Which would be a potential problem for scripts which somehow already had such a class with an underscore - but such systems would already break under BSF anyway. Any objections?

        I also think the method should be moved into some util class outside of BSF and then called from BSF and wherever else it is needed.

        Show
        Paul King added a comment - I think Roshan's suggestion of reusing org.codehaus.groovy.bsf.GroovyEngine#convertToValidJavaClassname() is the way to go. This would not remove characters like '-' but instead replace them with '_'. Which would be a potential problem for scripts which somehow already had such a class with an underscore - but such systems would already break under BSF anyway. Any objections? I also think the method should be moved into some util class outside of BSF and then called from BSF and wherever else it is needed.
        Hide
        blackdrag blackdrag added a comment -

        If we change the name it is not bijective any more. Well, being bijective is nice, but maybe not needed. Though having 2 possible source names for a given class name is one thing, having many more possibilities another. As soon as you have one script depending on another, that kind of name mangling will cause a problem. In https://blogs.oracle.com/jrose/entry/symbolic_freedom_in_the_vmsuggests to use an escaping mechanism instead. But the problem is that '-' is not part of that. Still we could take the idea and for example use
        + UTF16 hexadecimal number. That would then allow a 1:1 encoding and supports any UTF16 character

        Show
        blackdrag blackdrag added a comment - If we change the name it is not bijective any more. Well, being bijective is nice, but maybe not needed. Though having 2 possible source names for a given class name is one thing, having many more possibilities another. As soon as you have one script depending on another, that kind of name mangling will cause a problem. In https://blogs.oracle.com/jrose/entry/symbolic_freedom_in_the_vmsuggests to use an escaping mechanism instead. But the problem is that '-' is not part of that. Still we could take the idea and for example use + UTF16 hexadecimal number. That would then allow a 1:1 encoding and supports any UTF16 character

          People

          • Assignee:
            Unassigned
            Reporter:
            Tran The Trong
          • Votes:
            2 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: