Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 1.6-rc-2, 1.6-rc-3
    • Fix Version/s: 1.6.1, 1.5.8, 1.7-beta-1
    • Component/s: None
    • Labels:
      None
    • Testcase included:
      yes
    • Number of attachments :
      2

      Description

      Execute the following groovy script:

      def a = 1
      def b = "two"
      println "$

      {a}

      $

      {b}

      c".split()

      using

      java -ea -cp lib/groovy-all-1.6-RC-3.jar groovy.lang.GroovyShell test.groovy

      gives a NullPointerException with groovy-all-1.6-RC-2.jar or groovy-all-1.6-RC-3.jar, runs fine with groovy-all-1.5.7.jar.

      1. 3359.diff
        1 kB
        Chanwit Kaewkasi

        Activity

        Hide
        John A McDonald added a comment -

        Forgot the stack trace:

        Caught: java.lang.NullPointerException
        at test.run(test.groovy:3)

        Show
        John A McDonald added a comment - Forgot the stack trace: Caught: java.lang.NullPointerException at test.run(test.groovy:3)
        Hide
        Paul King added a comment -

        Yes, I can confirm this is an issue. The workaround in the specific example is to add a toString().
        What worries me is that in 1.5.7 and 1.6-beta2 we selected the split(String) method for this case
        but we now pick split(Object, Closure) with a null Closure. Tested on a client system not my own
        so I hope there is nothing local to that environment that is confusing the results I am seeing.
        It would be a worry if this is affecting all such calls. I'll have a little bit more of a look when I get
        home.

        Show
        Paul King added a comment - Yes, I can confirm this is an issue. The workaround in the specific example is to add a toString(). What worries me is that in 1.5.7 and 1.6-beta2 we selected the split(String) method for this case but we now pick split(Object, Closure) with a null Closure. Tested on a client system not my own so I hope there is nothing local to that environment that is confusing the results I am seeing. It would be a worry if this is affecting all such calls. I'll have a little bit more of a look when I get home.
        Hide
        Paul King added a comment -

        More complete stacktrace:

        java.lang.NullPointerException
                at org.codehaus.groovy.runtime.DefaultGroovyMethods.split(DefaultGroovyMethods.java:1748)
                at org.codehaus.groovy.runtime.DefaultGroovyMethods.split(DefaultGroovyMethods.java:1724)
                at org.codehaus.groovy.runtime.dgm$504.doMethodInvoke(Unknown Source)
                at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.invoke(PogoMetaMethodSite.java:42)
                at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:63)
                at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:43)
                at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
                at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
                at Test.run(Test.groovy:3)
                at groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:256)
                at groovy.lang.GroovyShell.run(GroovyShell.java:471)
                at groovy.lang.GroovyShell.run(GroovyShell.java:451)
                at groovy.lang.GroovyShell.run(GroovyShell.java:160)
                at groovy.lang.GroovyShell$run.call(Unknown Source)
                at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:43)
                at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
                at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:132)
                at groovy.ui.Console$_runScriptImpl_closure13.doCall(Console.groovy:732)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                at java.lang.reflect.Method.invoke(Method.java:597)
                at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
                at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234)
                at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
                at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:892)
                at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
                at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:47)
                at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:142)
                at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:150)
                at groovy.ui.Console$_runScriptImpl_closure13.doCall(Console.groovy)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                at java.lang.reflect.Method.invoke(Method.java:597)
                at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
                at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234)
                at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
                at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:892)
                at groovy.lang.Closure.call(Closure.java:279)
                at groovy.lang.Closure.call(Closure.java:274)
                at groovy.lang.Closure.run(Closure.java:355)
                at java.lang.Thread.run(Thread.java:619)
        
        Show
        Paul King added a comment - More complete stacktrace: java.lang.NullPointerException at org.codehaus.groovy.runtime.DefaultGroovyMethods.split(DefaultGroovyMethods.java:1748) at org.codehaus.groovy.runtime.DefaultGroovyMethods.split(DefaultGroovyMethods.java:1724) at org.codehaus.groovy.runtime.dgm$504.doMethodInvoke(Unknown Source) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.invoke(PogoMetaMethodSite.java:42) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:63) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:43) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120) at Test.run(Test.groovy:3) at groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:256) at groovy.lang.GroovyShell.run(GroovyShell.java:471) at groovy.lang.GroovyShell.run(GroovyShell.java:451) at groovy.lang.GroovyShell.run(GroovyShell.java:160) at groovy.lang.GroovyShell$run.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:43) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:132) at groovy.ui.Console$_runScriptImpl_closure13.doCall(Console.groovy:732) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:892) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:142) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:150) at groovy.ui.Console$_runScriptImpl_closure13.doCall(Console.groovy) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:892) at groovy.lang.Closure.call(Closure.java:279) at groovy.lang.Closure.call(Closure.java:274) at groovy.lang.Closure.run(Closure.java:355) at java.lang.Thread.run(Thread.java:619)
        Hide
        blackdrag blackdrag added a comment -

        I assume the fix for GROOVY-3106 in rev 13778 caused this problem. 1.5.8 has the problem too, because the method is there too, even though the issue doesn't tell that. as to why the Closure is null, that is because a one parameter method can be called without arguments by setting the argument to null. The fact that bothers me more is that only the Object method is seen at first and not the String version. I think String is in there as fallback, but that also means DGM methods defined for String don't overload those defined on for example Object... it seems they still override.

        Show
        blackdrag blackdrag added a comment - I assume the fix for GROOVY-3106 in rev 13778 caused this problem. 1.5.8 has the problem too, because the method is there too, even though the issue doesn't tell that. as to why the Closure is null, that is because a one parameter method can be called without arguments by setting the argument to null. The fact that bothers me more is that only the Object method is seen at first and not the String version. I think String is in there as fallback, but that also means DGM methods defined for String don't overload those defined on for example Object... it seems they still override.
        Hide
        Paul King added a comment - - edited

        Yes, GROOVY-3106 does seem to have caused the problem to surface but it isn't clear to me that the problem isn't broader than that issue. Is the behavior below what we expect:

        def gs = "The answer is ${42}"
        println gs instanceof GString // => true
        
        def foo(String x) { 'I am String foo' }
        def foo(Object y) { 'I am Object foo' }
        println foo(gs) // => I am String foo
        
        class MyCat {
          static bar(String x) { 'I am String bar' }
          static bar(Object y) { 'I am Object bar' }
        }
        use (MyCat) {
          println gs.bar() // => I am Object bar
        }
        

        I guess it is but should it be?

        Show
        Paul King added a comment - - edited Yes, GROOVY-3106 does seem to have caused the problem to surface but it isn't clear to me that the problem isn't broader than that issue. Is the behavior below what we expect: def gs = "The answer is ${42}" println gs instanceof GString // => true def foo( String x) { 'I am String foo' } def foo( Object y) { 'I am Object foo' } println foo(gs) // => I am String foo class MyCat { static bar( String x) { 'I am String bar' } static bar( Object y) { 'I am Object bar' } } use (MyCat) { println gs.bar() // => I am Object bar } I guess it is but should it be?
        Hide
        Paul King added a comment -

        OK, I went through all of the DGM methods and apart from esoteric examples like:

        new Date().asType()
        

        (which also produces a null instead of some nicer kind of message) I think
        split is the only case affected, so it seems like a split(Object) which did a toString()
        on self and then called through to split(String) might be the way to go here.

        Show
        Paul King added a comment - OK, I went through all of the DGM methods and apart from esoteric examples like: new Date().asType() (which also produces a null instead of some nicer kind of message) I think split is the only case affected, so it seems like a split(Object) which did a toString() on self and then called through to split(String) might be the way to go here.
        Hide
        Chanwit Kaewkasi added a comment -

        In the fix, I add static split(GString) to DGMs. So, MOP will pick this method rather than going into static split(Object, Closure), where Closure is always null for this test case (per Paul's comment).

        Show
        Chanwit Kaewkasi added a comment - In the fix, I add static split(GString) to DGMs. So, MOP will pick this method rather than going into static split(Object, Closure), where Closure is always null for this test case (per Paul's comment).
        Hide
        Paul King added a comment -

        Added DGM.split(GString) and tests

        Show
        Paul King added a comment - Added DGM.split(GString) and tests

          People

          • Assignee:
            Paul King
            Reporter:
            John A McDonald
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: