[jira] [Updated] (GROOVY-8336) Static compilation requires casting inside instanceof check (additional cases)
[ https://issues.apache.org/jira/browse/GROOVY-8336?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Paul King updated GROOVY-8336: -- Description: Cloned from GROOVY-8260 to handle these additional cases: {code} import groovy.transform.CompileStatic @CompileStatic Date ternaryParam(Object input) { input instanceof Date ? input : null } @CompileStatic Date ternaryLocalVar(Object input) { Object copy = input copy instanceof Date ? copy : null } @CompileStatic Date ifThenElseParam(Object ifThenElseInput) { if (ifThenElseInput instanceof Date) { ifThenElseInput } else { null } } @CompileStatic Date ifThenElseLocalVar(Object input) { Date result if (input instanceof Date) { result = input } else { result = null } result } class FooBase {} class FooChild extends FooBase{} @CompileStatic FooChild ifThenElseLocalVar2(FooBase input) { FooChild result if (input instanceof FooChild) { result = input } else { result = null } result } def d = new Date() assert ternaryParam(42) == null assert ternaryParam('foo') == null assert ternaryParam(d) == d assert ternaryLocalVar(42) == null assert ternaryLocalVar('foo') == null assert ternaryLocalVar(d) == d assert ifThenElseParam(42) == null assert ifThenElseParam('foo') == null assert ifThenElseParam(d) == d assert ifThenElseLocalVar(42) == null assert ifThenElseLocalVar('foo') == null assert ifThenElseLocalVar(d) == d def fc = new FooChild() assert ifThenElseLocalVar2(fc) == fc assert ifThenElseLocalVar2(new FooBase()) == null {code} was: There are many times I find myself having to cast variables directly inside an {{instanceof Class}} check. In addition, I have found a specific problem with a generic {{}} where a method in the class that returns {{T}}, Groovy believes a collection is being returned. This is the line in question: https://github.com/grails/gorm-graphql/blob/ea6887bef0ced75d9cc0d01dc7b94d4fc0520266/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/EntityDataFetcher.groovy#L45 The goal of this issue is to have the following codebase compile without changes. {{git clone -b broken_compilation https://github.com/grails/gorm-graphql}} Attempt to compile with {{./gradlew clean classes}} > Static compilation requires casting inside instanceof check (additional cases) > -- > > Key: GROOVY-8336 > URL: https://issues.apache.org/jira/browse/GROOVY-8336 > Project: Groovy > Issue Type: Bug > Components: Compiler >Affects Versions: 2.4.12 > Environment: macOS JDK 1.8 >Reporter: James Kleeh >Assignee: Paul King > Fix For: 2.4.13 > > > Cloned from GROOVY-8260 to handle these additional cases: > {code} > import groovy.transform.CompileStatic > @CompileStatic > Date ternaryParam(Object input) { > input instanceof Date ? input : null > } > @CompileStatic > Date ternaryLocalVar(Object input) { > Object copy = input > copy instanceof Date ? copy : null > } > @CompileStatic > Date ifThenElseParam(Object ifThenElseInput) { > if (ifThenElseInput instanceof Date) { > ifThenElseInput > } else { > null > } > } > @CompileStatic > Date ifThenElseLocalVar(Object input) { > Date result > if (input instanceof Date) { > result = input > } else { > result = null > } > result > } > class FooBase {} > class FooChild extends FooBase{} > @CompileStatic > FooChild ifThenElseLocalVar2(FooBase input) { > FooChild result > if (input instanceof FooChild) { > result = input > } else { > result = null > } > result > } > def d = new Date() > assert ternaryParam(42) == null > assert ternaryParam('foo') == null > assert ternaryParam(d) == d > assert ternaryLocalVar(42) == null > assert ternaryLocalVar('foo') == null > assert ternaryLocalVar(d) == d > assert ifThenElseParam(42) == null > assert ifThenElseParam('foo') == null > assert ifThenElseParam(d) == d > assert ifThenElseLocalVar(42) == null > assert ifThenElseLocalVar('foo') == null > assert ifThenElseLocalVar(d) == d > def fc = new FooChild() > assert ifThenElseLocalVar2(fc) == fc > assert ifThenElseLocalVar2(new FooBase()) == null > {code} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Created] (GROOVY-8336) Static compilation requires casting inside instanceof check (additional cases)
Paul King created GROOVY-8336: - Summary: Static compilation requires casting inside instanceof check (additional cases) Key: GROOVY-8336 URL: https://issues.apache.org/jira/browse/GROOVY-8336 Project: Groovy Issue Type: Bug Components: Compiler Affects Versions: 2.4.12 Environment: macOS JDK 1.8 Reporter: James Kleeh Assignee: Paul King Fix For: 2.4.13 There are many times I find myself having to cast variables directly inside an {{instanceof Class}} check. In addition, I have found a specific problem with a generic {{}} where a method in the class that returns {{T}}, Groovy believes a collection is being returned. This is the line in question: https://github.com/grails/gorm-graphql/blob/ea6887bef0ced75d9cc0d01dc7b94d4fc0520266/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/EntityDataFetcher.groovy#L45 The goal of this issue is to have the following codebase compile without changes. {{git clone -b broken_compilation https://github.com/grails/gorm-graphql}} Attempt to compile with {{./gradlew clean classes}} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Resolved] (GROOVY-8213) Closures are maybe not Threadsafe
[ https://issues.apache.org/jira/browse/GROOVY-8213?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] John Wagenleitner resolved GROOVY-8213. --- Resolution: Fixed Assignee: John Wagenleitner Fix Version/s: 2.4.13 I went ahead and merged the {{volatile}} change. Thanks for reporting the issue. Not sure how easy this will be to test with 2.4 snapshots, but if possible would like to get feedback on whether this fixes the issue you were seeing on the CI server. > Closures are maybe not Threadsafe > - > > Key: GROOVY-8213 > URL: https://issues.apache.org/jira/browse/GROOVY-8213 > Project: Groovy > Issue Type: Bug >Affects Versions: 2.4.10 > Environment: Gradle 3.5 >Reporter: Björn Kautler >Assignee: John Wagenleitner > Fix For: 2.4.13 > > > I just upgraded our Gradle build from 1.12 (including Groovy 1.8.6) to 3.5 > (including Groovy 2.4.10). > Now I get a very strange behavior for stuff that is there for years already > and it looks to me as if this is a Groovy bug, maybe a non-threadsafeness of > Closures. > I have a custom task that contains the following code: > {code} > def sourceFilesSize = getSourceFiles().files.size() > def poolSize = Runtime.runtime.availableProcessors() > def executor = new ThreadPoolExecutor(poolSize, poolSize, 0, SECONDS, > new ArrayBlockingQueue([sourceFilesSize, 1].max())) > def tasks = [] > inputs.outOfDate { toTransform -> > tasks.add executor.submit { > project.exec { >if (gscPath) { // here starts > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > environment 'GSC', gscPath > def tempDir = "$temporaryDir/${Thread.currentThread().name}" > project.file(tempDir).mkdirs() > environment 'TEMP', tempDir >} >executable executablePath >def arguments = [toTransform.file.absolutePath] >if ((sourceFilesSize == 1) && getDestinationFile()) { > arguments << getDestinationFile().absolutePath >} else if (destinationDirectory) { > arguments << new File(destinationDirectory, > fileNameMapping(toTransform.file.name)).absolutePath >} else { > arguments << new File(toTransform.file.parentFile, > fileNameMapping(toTransform.file.name)).absolutePath >} >args arguments // here ends > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > } > } > } > executor.shutdown() > executor.awaitTermination 1, HOURS > tasks*.get() // here is line 137 > {code} > When this task is executed e. g. with five source files, sometimes all works > fine, sometime the build fails with > {noformat} > ... > Caused by: java.util.concurrent.ExecutionException: > java.lang.IllegalStateException: initialize must be called for meta class of > class com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > at com.empic.build.tasks.Ghostscript.exec(Ghostscript.groovy:137) > at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73) > ... 80 more > Caused by: java.lang.IllegalStateException: initialize must be called for > meta class of class > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > {noformat} > Actually I was not able to reproduce the problem locally, but if I run the > build on our CI server and attach a debugger, I indeed was able to reproduce > the problem with a relatively high reproduction rate. (as in every second to > third build approximately, opposed to once every 100 builds) > I logged the current thread when the {{initialized}} property is set to > {{true}} and when it is requested with non-suspending breakpoints, but this > seems to have caused the timing to change enough already that I was not able > to reproduce the error within approximately the first two dozens of tries. > I was able to successfully break at the throwing of the > {{IllegalStateException}} though. This happens in > {{groovy.lang.MetaClassImpl.checkInitalised}}. > The stacktrace at this point is: > {noformat} > "pool-2-thread-3@10709" prio=5 tid=0x47 nid=NA runnable > java.lang.Thread.State: RUNNABLE > at groovy.lang.MetaClassImpl.checkInitalised(MetaClassImpl.java:1647) > at >
[jira] [Commented] (GROOVY-8213) Closures are maybe not Threadsafe
[ https://issues.apache.org/jira/browse/GROOVY-8213?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16187281#comment-16187281 ] ASF GitHub Bot commented on GROOVY-8213: Github user asfgit closed the pull request at: https://github.com/apache/groovy/pull/609 > Closures are maybe not Threadsafe > - > > Key: GROOVY-8213 > URL: https://issues.apache.org/jira/browse/GROOVY-8213 > Project: Groovy > Issue Type: Bug >Affects Versions: 2.4.10 > Environment: Gradle 3.5 >Reporter: Björn Kautler > > I just upgraded our Gradle build from 1.12 (including Groovy 1.8.6) to 3.5 > (including Groovy 2.4.10). > Now I get a very strange behavior for stuff that is there for years already > and it looks to me as if this is a Groovy bug, maybe a non-threadsafeness of > Closures. > I have a custom task that contains the following code: > {code} > def sourceFilesSize = getSourceFiles().files.size() > def poolSize = Runtime.runtime.availableProcessors() > def executor = new ThreadPoolExecutor(poolSize, poolSize, 0, SECONDS, > new ArrayBlockingQueue([sourceFilesSize, 1].max())) > def tasks = [] > inputs.outOfDate { toTransform -> > tasks.add executor.submit { > project.exec { >if (gscPath) { // here starts > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > environment 'GSC', gscPath > def tempDir = "$temporaryDir/${Thread.currentThread().name}" > project.file(tempDir).mkdirs() > environment 'TEMP', tempDir >} >executable executablePath >def arguments = [toTransform.file.absolutePath] >if ((sourceFilesSize == 1) && getDestinationFile()) { > arguments << getDestinationFile().absolutePath >} else if (destinationDirectory) { > arguments << new File(destinationDirectory, > fileNameMapping(toTransform.file.name)).absolutePath >} else { > arguments << new File(toTransform.file.parentFile, > fileNameMapping(toTransform.file.name)).absolutePath >} >args arguments // here ends > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > } > } > } > executor.shutdown() > executor.awaitTermination 1, HOURS > tasks*.get() // here is line 137 > {code} > When this task is executed e. g. with five source files, sometimes all works > fine, sometime the build fails with > {noformat} > ... > Caused by: java.util.concurrent.ExecutionException: > java.lang.IllegalStateException: initialize must be called for meta class of > class com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > at com.empic.build.tasks.Ghostscript.exec(Ghostscript.groovy:137) > at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73) > ... 80 more > Caused by: java.lang.IllegalStateException: initialize must be called for > meta class of class > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > {noformat} > Actually I was not able to reproduce the problem locally, but if I run the > build on our CI server and attach a debugger, I indeed was able to reproduce > the problem with a relatively high reproduction rate. (as in every second to > third build approximately, opposed to once every 100 builds) > I logged the current thread when the {{initialized}} property is set to > {{true}} and when it is requested with non-suspending breakpoints, but this > seems to have caused the timing to change enough already that I was not able > to reproduce the error within approximately the first two dozens of tries. > I was able to successfully break at the throwing of the > {{IllegalStateException}} though. This happens in > {{groovy.lang.MetaClassImpl.checkInitalised}}. > The stacktrace at this point is: > {noformat} > "pool-2-thread-3@10709" prio=5 tid=0x47 nid=NA runnable > java.lang.Thread.State: RUNNABLE > at groovy.lang.MetaClassImpl.checkInitalised(MetaClassImpl.java:1647) > at > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:257) > at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1027) > at groovy.lang.Closure.call(Closure.java:414) > at groovy.lang.Closure.call(Closure.java:408) > at groovy.lang.Closure.run(Closure.java:495)
[GitHub] groovy pull request #609: GROOVY-8213: Closures are maybe not Threadsafe
Github user asfgit closed the pull request at: https://github.com/apache/groovy/pull/609 ---
[jira] [Commented] (GROOVY-8326) @Override should not copied onto methods generated by applying @Memoize
[ https://issues.apache.org/jira/browse/GROOVY-8326?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16187277#comment-16187277 ] ASF GitHub Bot commented on GROOVY-8326: GitHub user jwagenleitner opened a pull request: https://github.com/apache/groovy/pull/610 GROOVY-8326: @Override should not copied onto methods generated by ap… …plying @Memoize You can merge this pull request into a Git repository by running: $ git pull https://github.com/jwagenleitner/groovy 8326-Memoized-Override Alternatively you can review and apply these changes as the patch at: https://github.com/apache/groovy/pull/610.patch To close this pull request, make a commit to your master/trunk branch with (at least) the following in the commit message: This closes #610 commit 8bb23c4a5574925a1eecfe57b1a8acbcafbbcb5a Author: John WagenleitnerDate: 2017-10-01T04:06:49Z GROOVY-8326: @Override should not copied onto methods generated by applying @Memoize > @Override should not copied onto methods generated by applying @Memoize > --- > > Key: GROOVY-8326 > URL: https://issues.apache.org/jira/browse/GROOVY-8326 > Project: Groovy > Issue Type: Bug >Affects Versions: 2.4.12 >Reporter: Marcin Erdmann >Priority: Minor > Labels: ast > > Applying {{@Memoized}} onto a method already annotated with {{@Override}} > will result in a compilation error along the lines of: > {quote} > Method 'memoizedMethodPriv$...' from class '...' does not override method > from its superclass or interfaces but is annotated with @Override. > {quote} > This is because all annotations of the method annotated with {{@Memoized}} > are copied onto the method generated by the AST > [here|https://github.com/apache/groovy/blob/731d4daa78b9cd32bea724d2d651aa1164eef6cc/src/main/org/codehaus/groovy/transform/MemoizedASTTransformation.java#L131]. > In my opinion {{java.lang.Override}} should be filtered out. -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[GitHub] groovy pull request #610: GROOVY-8326: @Override should not copied onto meth...
GitHub user jwagenleitner opened a pull request: https://github.com/apache/groovy/pull/610 GROOVY-8326: @Override should not copied onto methods generated by ap⦠â¦plying @Memoize You can merge this pull request into a Git repository by running: $ git pull https://github.com/jwagenleitner/groovy 8326-Memoized-Override Alternatively you can review and apply these changes as the patch at: https://github.com/apache/groovy/pull/610.patch To close this pull request, make a commit to your master/trunk branch with (at least) the following in the commit message: This closes #610 commit 8bb23c4a5574925a1eecfe57b1a8acbcafbbcb5a Author: John WagenleitnerDate: 2017-10-01T04:06:49Z GROOVY-8326: @Override should not copied onto methods generated by applying @Memoize ---
[jira] [Commented] (GROOVY-8213) Closures are maybe not Threadsafe
[ https://issues.apache.org/jira/browse/GROOVY-8213?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16187273#comment-16187273 ] Paul King commented on GROOVY-8213: --- I haven't thought through whether there are any scenarios not covered by your tests John, but it seems from the results that in many cases there will be negligible performance degradation and improved stability, seems like a no-brainer to include this. > Closures are maybe not Threadsafe > - > > Key: GROOVY-8213 > URL: https://issues.apache.org/jira/browse/GROOVY-8213 > Project: Groovy > Issue Type: Bug >Affects Versions: 2.4.10 > Environment: Gradle 3.5 >Reporter: Björn Kautler > > I just upgraded our Gradle build from 1.12 (including Groovy 1.8.6) to 3.5 > (including Groovy 2.4.10). > Now I get a very strange behavior for stuff that is there for years already > and it looks to me as if this is a Groovy bug, maybe a non-threadsafeness of > Closures. > I have a custom task that contains the following code: > {code} > def sourceFilesSize = getSourceFiles().files.size() > def poolSize = Runtime.runtime.availableProcessors() > def executor = new ThreadPoolExecutor(poolSize, poolSize, 0, SECONDS, > new ArrayBlockingQueue([sourceFilesSize, 1].max())) > def tasks = [] > inputs.outOfDate { toTransform -> > tasks.add executor.submit { > project.exec { >if (gscPath) { // here starts > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > environment 'GSC', gscPath > def tempDir = "$temporaryDir/${Thread.currentThread().name}" > project.file(tempDir).mkdirs() > environment 'TEMP', tempDir >} >executable executablePath >def arguments = [toTransform.file.absolutePath] >if ((sourceFilesSize == 1) && getDestinationFile()) { > arguments << getDestinationFile().absolutePath >} else if (destinationDirectory) { > arguments << new File(destinationDirectory, > fileNameMapping(toTransform.file.name)).absolutePath >} else { > arguments << new File(toTransform.file.parentFile, > fileNameMapping(toTransform.file.name)).absolutePath >} >args arguments // here ends > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > } > } > } > executor.shutdown() > executor.awaitTermination 1, HOURS > tasks*.get() // here is line 137 > {code} > When this task is executed e. g. with five source files, sometimes all works > fine, sometime the build fails with > {noformat} > ... > Caused by: java.util.concurrent.ExecutionException: > java.lang.IllegalStateException: initialize must be called for meta class of > class com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > at com.empic.build.tasks.Ghostscript.exec(Ghostscript.groovy:137) > at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73) > ... 80 more > Caused by: java.lang.IllegalStateException: initialize must be called for > meta class of class > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > {noformat} > Actually I was not able to reproduce the problem locally, but if I run the > build on our CI server and attach a debugger, I indeed was able to reproduce > the problem with a relatively high reproduction rate. (as in every second to > third build approximately, opposed to once every 100 builds) > I logged the current thread when the {{initialized}} property is set to > {{true}} and when it is requested with non-suspending breakpoints, but this > seems to have caused the timing to change enough already that I was not able > to reproduce the error within approximately the first two dozens of tries. > I was able to successfully break at the throwing of the > {{IllegalStateException}} though. This happens in > {{groovy.lang.MetaClassImpl.checkInitalised}}. > The stacktrace at this point is: > {noformat} > "pool-2-thread-3@10709" prio=5 tid=0x47 nid=NA runnable > java.lang.Thread.State: RUNNABLE > at groovy.lang.MetaClassImpl.checkInitalised(MetaClassImpl.java:1647) > at > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:257) > at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1027) > at
[jira] [Commented] (GROOVY-8213) Closures are maybe not Threadsafe
[ https://issues.apache.org/jira/browse/GROOVY-8213?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16187270#comment-16187270 ] ASF GitHub Bot commented on GROOVY-8213: GitHub user jwagenleitner opened a pull request: https://github.com/apache/groovy/pull/609 GROOVY-8213: Closures are maybe not Threadsafe To address @blackdrag 's comment in the JIRA I created a JMH benchmark to test a volatile read vs a recheck and sync, https://github.com/jwagenleitner/testing-groovy/tree/master/issues/groovy8213. Based on my runs the volatile read is very close to a normal read. Doing a branched check (without needing to sync) was actually worse in terms of performance. It seems with the `--parallel` feature in Gradle and builds being run on large many core servers this problem seems to be coming up more frequently. See https://github.com/gradle/gradle/issues/1420. While I do believe the publication of the `initialized` variable is an issue and should be addressed, another possible cause of this sort of problem could be related to the way the [`respondTo` methods are implemented by unsetting the `initialized` variable during a call to `super.initialize()` in the `loadMetaInfo() ` method](https://github.com/apache/groovy/blob/7b101dd98ffc04b1bfd2447bbe277340d8954add/src/main/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java#L724-L740). But in this case and the referenced Gradle issue I'm not sure the `respondTo` methods are in play. You can merge this pull request into a Git repository by running: $ git pull https://github.com/jwagenleitner/groovy 8213-Closure-Init-Threadsafe Alternatively you can review and apply these changes as the patch at: https://github.com/apache/groovy/pull/609.patch To close this pull request, make a commit to your master/trunk branch with (at least) the following in the commit message: This closes #609 commit 01946dbf2bdd11bb1fa402131ba50fef26f889eb Author: John WagenleitnerDate: 2017-10-01T02:31:16Z GROOVY-8213: Closures are maybe not Threadsafe > Closures are maybe not Threadsafe > - > > Key: GROOVY-8213 > URL: https://issues.apache.org/jira/browse/GROOVY-8213 > Project: Groovy > Issue Type: Bug >Affects Versions: 2.4.10 > Environment: Gradle 3.5 >Reporter: Björn Kautler > > I just upgraded our Gradle build from 1.12 (including Groovy 1.8.6) to 3.5 > (including Groovy 2.4.10). > Now I get a very strange behavior for stuff that is there for years already > and it looks to me as if this is a Groovy bug, maybe a non-threadsafeness of > Closures. > I have a custom task that contains the following code: > {code} > def sourceFilesSize = getSourceFiles().files.size() > def poolSize = Runtime.runtime.availableProcessors() > def executor = new ThreadPoolExecutor(poolSize, poolSize, 0, SECONDS, > new ArrayBlockingQueue([sourceFilesSize, 1].max())) > def tasks = [] > inputs.outOfDate { toTransform -> > tasks.add executor.submit { > project.exec { >if (gscPath) { // here starts > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > environment 'GSC', gscPath > def tempDir = "$temporaryDir/${Thread.currentThread().name}" > project.file(tempDir).mkdirs() > environment 'TEMP', tempDir >} >executable executablePath >def arguments = [toTransform.file.absolutePath] >if ((sourceFilesSize == 1) && getDestinationFile()) { > arguments << getDestinationFile().absolutePath >} else if (destinationDirectory) { > arguments << new File(destinationDirectory, > fileNameMapping(toTransform.file.name)).absolutePath >} else { > arguments << new File(toTransform.file.parentFile, > fileNameMapping(toTransform.file.name)).absolutePath >} >args arguments // here ends > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > } > } > } > executor.shutdown() > executor.awaitTermination 1, HOURS > tasks*.get() // here is line 137 > {code} > When this task is executed e. g. with five source files, sometimes all works > fine, sometime the build fails with > {noformat} > ... > Caused by: java.util.concurrent.ExecutionException: > java.lang.IllegalStateException: initialize must be called for meta class of > class com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done >
[GitHub] groovy pull request #609: GROOVY-8213: Closures are maybe not Threadsafe
GitHub user jwagenleitner opened a pull request: https://github.com/apache/groovy/pull/609 GROOVY-8213: Closures are maybe not Threadsafe To address @blackdrag 's comment in the JIRA I created a JMH benchmark to test a volatile read vs a recheck and sync, https://github.com/jwagenleitner/testing-groovy/tree/master/issues/groovy8213. Based on my runs the volatile read is very close to a normal read. Doing a branched check (without needing to sync) was actually worse in terms of performance. It seems with the `--parallel` feature in Gradle and builds being run on large many core servers this problem seems to be coming up more frequently. See https://github.com/gradle/gradle/issues/1420. While I do believe the publication of the `initialized` variable is an issue and should be addressed, another possible cause of this sort of problem could be related to the way the [`respondTo` methods are implemented by unsetting the `initialized` variable during a call to `super.initialize()` in the `loadMetaInfo() ` method](https://github.com/apache/groovy/blob/7b101dd98ffc04b1bfd2447bbe277340d8954add/src/main/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java#L724-L740). But in this case and the referenced Gradle issue I'm not sure the `respondTo` methods are in play. You can merge this pull request into a Git repository by running: $ git pull https://github.com/jwagenleitner/groovy 8213-Closure-Init-Threadsafe Alternatively you can review and apply these changes as the patch at: https://github.com/apache/groovy/pull/609.patch To close this pull request, make a commit to your master/trunk branch with (at least) the following in the commit message: This closes #609 commit 01946dbf2bdd11bb1fa402131ba50fef26f889eb Author: John WagenleitnerDate: 2017-10-01T02:31:16Z GROOVY-8213: Closures are maybe not Threadsafe ---
[jira] [Commented] (GROOVY-8213) Closures are maybe not Threadsafe
[ https://issues.apache.org/jira/browse/GROOVY-8213?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16187269#comment-16187269 ] John Wagenleitner commented on GROOVY-8213: --- A related Gradle issue is https://github.com/gradle/gradle/issues/1420. While I do believe the publication of the {{initialized}} variable could be an issue and should be addressed, another possible cause of this could be related to the way the {{respondTo}} methods are implemented by unsetting the {{initialized}} variable during a call to {{super.initialize()}} in the {{loadMetaInfo()}} method. https://github.com/apache/groovy/blob/7b101dd98ffc04b1bfd2447bbe277340d8954add/src/main/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java#L724-L740 But in this case and the Gradle issue I'm not sure the {{respondTo}} methods are in play. > Closures are maybe not Threadsafe > - > > Key: GROOVY-8213 > URL: https://issues.apache.org/jira/browse/GROOVY-8213 > Project: Groovy > Issue Type: Bug >Affects Versions: 2.4.10 > Environment: Gradle 3.5 >Reporter: Björn Kautler > > I just upgraded our Gradle build from 1.12 (including Groovy 1.8.6) to 3.5 > (including Groovy 2.4.10). > Now I get a very strange behavior for stuff that is there for years already > and it looks to me as if this is a Groovy bug, maybe a non-threadsafeness of > Closures. > I have a custom task that contains the following code: > {code} > def sourceFilesSize = getSourceFiles().files.size() > def poolSize = Runtime.runtime.availableProcessors() > def executor = new ThreadPoolExecutor(poolSize, poolSize, 0, SECONDS, > new ArrayBlockingQueue([sourceFilesSize, 1].max())) > def tasks = [] > inputs.outOfDate { toTransform -> > tasks.add executor.submit { > project.exec { >if (gscPath) { // here starts > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > environment 'GSC', gscPath > def tempDir = "$temporaryDir/${Thread.currentThread().name}" > project.file(tempDir).mkdirs() > environment 'TEMP', tempDir >} >executable executablePath >def arguments = [toTransform.file.absolutePath] >if ((sourceFilesSize == 1) && getDestinationFile()) { > arguments << getDestinationFile().absolutePath >} else if (destinationDirectory) { > arguments << new File(destinationDirectory, > fileNameMapping(toTransform.file.name)).absolutePath >} else { > arguments << new File(toTransform.file.parentFile, > fileNameMapping(toTransform.file.name)).absolutePath >} >args arguments // here ends > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > } > } > } > executor.shutdown() > executor.awaitTermination 1, HOURS > tasks*.get() // here is line 137 > {code} > When this task is executed e. g. with five source files, sometimes all works > fine, sometime the build fails with > {noformat} > ... > Caused by: java.util.concurrent.ExecutionException: > java.lang.IllegalStateException: initialize must be called for meta class of > class com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > at com.empic.build.tasks.Ghostscript.exec(Ghostscript.groovy:137) > at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73) > ... 80 more > Caused by: java.lang.IllegalStateException: initialize must be called for > meta class of class > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > {noformat} > Actually I was not able to reproduce the problem locally, but if I run the > build on our CI server and attach a debugger, I indeed was able to reproduce > the problem with a relatively high reproduction rate. (as in every second to > third build approximately, opposed to once every 100 builds) > I logged the current thread when the {{initialized}} property is set to > {{true}} and when it is requested with non-suspending breakpoints, but this > seems to have caused the timing to change enough already that I was not able > to reproduce the error within approximately the first two dozens of tries. > I was able to successfully break at the throwing of the > {{IllegalStateException}} though. This happens in > {{groovy.lang.MetaClassImpl.checkInitalised}}. > The
[jira] [Commented] (GROOVY-8213) Closures are maybe not Threadsafe
[ https://issues.apache.org/jira/browse/GROOVY-8213?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16187262#comment-16187262 ] John Wagenleitner commented on GROOVY-8213: --- I created a JMH benchmark to test a volatile read vs a recheck and sync, https://github.com/jwagenleitner/testing-groovy/tree/master/issues/groovy8213. Based on my runs the volatile read is very close to a normal read. Doing a branched check (without needing to sync) was actually worse in terms of performance. Based on those benchmarks I'd suggest making {{initialized}} volatile in both {{ClosureMetaClass}} and also in {{MetaClassImpl}}. > Closures are maybe not Threadsafe > - > > Key: GROOVY-8213 > URL: https://issues.apache.org/jira/browse/GROOVY-8213 > Project: Groovy > Issue Type: Bug >Affects Versions: 2.4.10 > Environment: Gradle 3.5 >Reporter: Björn Kautler > > I just upgraded our Gradle build from 1.12 (including Groovy 1.8.6) to 3.5 > (including Groovy 2.4.10). > Now I get a very strange behavior for stuff that is there for years already > and it looks to me as if this is a Groovy bug, maybe a non-threadsafeness of > Closures. > I have a custom task that contains the following code: > {code} > def sourceFilesSize = getSourceFiles().files.size() > def poolSize = Runtime.runtime.availableProcessors() > def executor = new ThreadPoolExecutor(poolSize, poolSize, 0, SECONDS, > new ArrayBlockingQueue([sourceFilesSize, 1].max())) > def tasks = [] > inputs.outOfDate { toTransform -> > tasks.add executor.submit { > project.exec { >if (gscPath) { // here starts > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > environment 'GSC', gscPath > def tempDir = "$temporaryDir/${Thread.currentThread().name}" > project.file(tempDir).mkdirs() > environment 'TEMP', tempDir >} >executable executablePath >def arguments = [toTransform.file.absolutePath] >if ((sourceFilesSize == 1) && getDestinationFile()) { > arguments << getDestinationFile().absolutePath >} else if (destinationDirectory) { > arguments << new File(destinationDirectory, > fileNameMapping(toTransform.file.name)).absolutePath >} else { > arguments << new File(toTransform.file.parentFile, > fileNameMapping(toTransform.file.name)).absolutePath >} >args arguments // here ends > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11 > } > } > } > executor.shutdown() > executor.awaitTermination 1, HOURS > tasks*.get() // here is line 137 > {code} > When this task is executed e. g. with five source files, sometimes all works > fine, sometime the build fails with > {noformat} > ... > Caused by: java.util.concurrent.ExecutionException: > java.lang.IllegalStateException: initialize must be called for meta class of > class com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > at com.empic.build.tasks.Ghostscript.exec(Ghostscript.groovy:137) > at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73) > ... 80 more > Caused by: java.lang.IllegalStateException: initialize must be called for > meta class of class > com.empic.build.tasks.Ghostscript$_exec_closure8$_closure11(class > org.codehaus.groovy.runtime.metaclass.ClosureMetaClass) to complete > initialisation process before any invocation or field/property access can be > done > {noformat} > Actually I was not able to reproduce the problem locally, but if I run the > build on our CI server and attach a debugger, I indeed was able to reproduce > the problem with a relatively high reproduction rate. (as in every second to > third build approximately, opposed to once every 100 builds) > I logged the current thread when the {{initialized}} property is set to > {{true}} and when it is requested with non-suspending breakpoints, but this > seems to have caused the timing to change enough already that I was not able > to reproduce the error within approximately the first two dozens of tries. > I was able to successfully break at the throwing of the > {{IllegalStateException}} though. This happens in > {{groovy.lang.MetaClassImpl.checkInitalised}}. > The stacktrace at this point is: > {noformat} > "pool-2-thread-3@10709" prio=5 tid=0x47 nid=NA runnable > java.lang.Thread.State: RUNNABLE > at
[jira] [Comment Edited] (GROOVY-8329) Consider statically typed/compiled as default for Groovy 3.0
[ https://issues.apache.org/jira/browse/GROOVY-8329?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16187217#comment-16187217 ] Endre Stølsvik edited comment on GROOVY-8329 at 9/30/17 10:01 PM: -- First off, I actually use Groovy quite a bit these days. I do all "prototyping" and much of the actual coding in Groovy, and Java has become more of the "API level language" - that is, I still consider my at-work projects to be Java, so the app-internal API is pure Java (and Groovy-specifics cannot be passed around, i.e. Closures) - but most actual code ends up being Groovy. If this makes sense. But: I pretty much _never_ use the dynamic parts of it - I use @CompileStatic on every single class, except on the few parts where I actually want to use the delegates and methodMissing and this stuff, i.e. DSLs - and also the few times I want to dynamically invoke stuff based on strings, like mentioned above. It is just so much simpler than introspection. Also, the GroovyShell with its Binding - love it! (I've made a JRebel-like tool that I use in exploratory settings: https://github.com/stolsvik/groovy-egl - but even inside scripts I slap @CompileStatic on everything!) I actually got slightly shocked when I first came over the @CompileStatic - most of my Groovy stuff compiled just fine right away when I added the @CompileStatic over it. I had at least expected Closures to immediately be banned, but no. Sometimes I forget the annotation, and I get annoyed why things crash in runtime, and then I see the IntelliJ "greyness" over a part in the code, slap on @CompileStatic, and lo and behold - it turns red. It would have been caught by the compiler, but since it is dynamic, it _might_ have worked, so the compiler can't stop you from calling toStriing().. I love Types. So my point is this: It works already! Typing is fantastic, and Groovy is in my eyes a fine typed language! I just find it sad that a language which has so much niceness with it, is dynamically typed by default, and not the other way: The dynamic abilities is the optional part which you can opt-in to use on specific parts. Configscript is something "outside" of the groovy files. And that immediately makes things more problematic: this option needs to be part of any compile stage, in any build, and the IDEs. Anway, I just wanted to chip in an opinion from a fan - but based on the reactions, it doesn't really seem like it will happen! Hey, this literally just hit me when about to hit "Add comment": *What about a different file-ending for statically compiled groovy files?! "HelloWorld.groovys"!* I made GROOVY-8335 for that suggestion. was (Author: stolsvik): First off, I actually use Groovy quite a bit these days. I do all "prototyping" and much of the actual coding in Groovy, and Java has become more of the "API level language" - that is, I still consider my at-work projects to be Java, so the app-internal API is pure Java (and Groovy-specifics cannot be passed around, i.e. Closures) - but most actual code ends up being Groovy. If this makes sense. But: I pretty much _never_ use the dynamic parts of it - I use @CompileStatic on every single class, except on the few parts where I actually want to use the delegates and methodMissing and this stuff, i.e. DSLs - and also the few times I want to dynamically invoke stuff based on strings, like mentioned above. It is just so much simpler than introspection. Also, the GroovyShell with its Binding - love it! (I've made a JRebel-like tool that I use in exploratory settings: https://github.com/stolsvik/groovy-egl - but even inside scripts I slap @CompileStatic on everything!) I actually got slightly shocked when I first came over the @CompileStatic - most of my Groovy stuff compiled just fine right away when I added the @CompileStatic over it. I had at least expected Closures to immediately be banned, but no. Sometimes I forget the annotation, and I get annoyed why things crash in runtime, and then I see the IntelliJ "greyness" over a part in the code, slap on @CompileStatic, and lo and behold - it turns red. It would have been caught by the compiler, but since it is dynamic, it _might_ have worked, so the compiler can't stop you from calling toStriing().. I love Types. So my point is this: It works already! Typing is fantastic, and Groovy is in my eyes a fine typed language! I just find it sad that a language which has so much niceness with it, is dynamically typed by default, and not the other way: The dynamic abilities is the optional part which you can opt-in to use on specific parts. Configscript is something "outside" of the groovy files. And that immediately makes things more problematic: this option needs to be part of any compile stage, in any build, and the IDEs. Anway, I just wanted to chip in an opinion from a fan - but based on the reactions, it
[jira] [Updated] (GROOVY-8335) Statically typed file ending: "HelloWorld.groovys" is considered @CompileStatic
[ https://issues.apache.org/jira/browse/GROOVY-8335?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Endre Stølsvik updated GROOVY-8335: --- Description: As a follow-up to GROOVY-8329 _"Consider statically typed/compiled as default for Groovy 3.0"_, which got a somewhat lukewarm reception, I suggest adding a new file-ending to the groovy universe: "groovys" (or something else entirely, just a suggestion). A file with this ending is a Groovy-file, but is @CompileStatic - and any methods where one wants the dynamic features of Groovy must be tagged with @CompileDynamic. *We'll get two languages in one!* was: As a follow-up to JIRA-8329 _"Consider statically typed/compiled as default for Groovy 3.0"_, which got a somewhat lukewarm reception, I suggest adding a new file-ending to the groovy universe: "groovys" (or something else entirely, just a suggestion). A file with this ending is a Groovy-file, but is @CompileStatic - and any methods where one wants the dynamic features of Groovy must be tagged with @CompileDynamic. *We'll get two languages in one!* > Statically typed file ending: "HelloWorld.groovys" is considered > @CompileStatic > --- > > Key: GROOVY-8335 > URL: https://issues.apache.org/jira/browse/GROOVY-8335 > Project: Groovy > Issue Type: Improvement >Reporter: Endre Stølsvik > > As a follow-up to GROOVY-8329 _"Consider statically typed/compiled as default > for Groovy 3.0"_, which got a somewhat lukewarm reception, I suggest adding a > new file-ending to the groovy universe: "groovys" (or something else > entirely, just a suggestion). A file with this ending is a Groovy-file, but > is @CompileStatic - and any methods where one wants the dynamic features of > Groovy must be tagged with @CompileDynamic. > *We'll get two languages in one!* -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Updated] (GROOVY-8335) Statically typed file ending: "HelloWorld.groovys" is considered @CompileStatic
[ https://issues.apache.org/jira/browse/GROOVY-8335?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Endre Stølsvik updated GROOVY-8335: --- Description: As a follow-up to JIRA-8329 _"Consider statically typed/compiled as default for Groovy 3.0"_, which got a somewhat lukewarm reception, I suggest adding a new file-ending to the groovy universe: "groovys" (or something else entirely, just a suggestion). A file with this ending is a Groovy-file, but is @CompileStatic - and any methods where one wants the dynamic features of Groovy must be tagged with @CompileDynamic. *We'll get two languages in one!* was: As a follow-up to JIRA-8329 _"Consider statically typed/compiled as default for Groovy 3.0"_, which got a somewhat lukewarm reception (!), I suggest adding a new file-ending to the groovy universe: "groovys" (or something else entirely, just a suggestion). A file with this ending is a Groovy-file, but is @CompileStatic - and any methods where one wants the dynamic features of Groovy must be tagged with @CompileDynamic. *We'll get two languages in one!* > Statically typed file ending: "HelloWorld.groovys" is considered > @CompileStatic > --- > > Key: GROOVY-8335 > URL: https://issues.apache.org/jira/browse/GROOVY-8335 > Project: Groovy > Issue Type: Improvement >Reporter: Endre Stølsvik > > As a follow-up to JIRA-8329 _"Consider statically typed/compiled as default > for Groovy 3.0"_, which got a somewhat lukewarm reception, I suggest adding a > new file-ending to the groovy universe: "groovys" (or something else > entirely, just a suggestion). A file with this ending is a Groovy-file, but > is @CompileStatic - and any methods where one wants the dynamic features of > Groovy must be tagged with @CompileDynamic. > *We'll get two languages in one!* -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Created] (GROOVY-8335) Statically typed file ending: "HelloWorld.groovys" is considered @CompileStatic
Endre Stølsvik created GROOVY-8335: -- Summary: Statically typed file ending: "HelloWorld.groovys" is considered @CompileStatic Key: GROOVY-8335 URL: https://issues.apache.org/jira/browse/GROOVY-8335 Project: Groovy Issue Type: Improvement Reporter: Endre Stølsvik As a follow-up to JIRA-8329 _"Consider statically typed/compiled as default for Groovy 3.0"_, which got a somewhat lukewarm reception (!), I suggest adding a new file-ending to the groovy universe: "groovys" (or something else entirely, just a suggestion). A file with this ending is a Groovy-file, but is @CompileStatic - and any methods where one wants the dynamic features of Groovy must be tagged with @CompileDynamic. *We'll get two languages in one!* -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Commented] (GROOVY-8329) Consider statically typed/compiled as default for Groovy 3.0
[ https://issues.apache.org/jira/browse/GROOVY-8329?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16187217#comment-16187217 ] Endre Stølsvik commented on GROOVY-8329: First off, I actually use Groovy quite a bit these days. I do all "prototyping" and much of the actual coding in Groovy, and Java has become more of the "API level language" - that is, I still consider my at-work projects to be Java, so the app-internal API is pure Java (and Groovy-specifics cannot be passed around, i.e. Closures) - but most actual code ends up being Groovy. If this makes sense. But: I pretty much _never_ use the dynamic parts of it - I use @CompileStatic on every single class, except on the few parts where I actually want to use the delegates and methodMissing and this stuff, i.e. DSLs - and also the few times I want to dynamically invoke stuff based on strings, like mentioned above. It is just so much simpler than introspection. Also, the GroovyShell with its Binding - love it! (I've made a JRebel-like tool that I use in exploratory settings: https://github.com/stolsvik/groovy-egl - but even inside scripts I slap @CompileStatic on everything!) I actually got slightly shocked when I first came over the @CompileStatic - most of my Groovy stuff compiled just fine right away when I added the @CompileStatic over it. I had at least expected Closures to immediately be banned, but no. Sometimes I forget the annotation, and I get annoyed why things crash in runtime, and then I see the IntelliJ "greyness" over a part in the code, slap on @CompileStatic, and lo and behold - it turns red. It would have been caught by the compiler, but since it is dynamic, it _might_ have worked, so the compiler can't stop you from calling toStriing().. I love Types. So my point is this: It works already! Typing is fantastic, and Groovy is in my eyes a fine typed language! I just find it sad that a language which has so much niceness with it, is dynamically typed by default, and not the other way: The dynamic abilities is the optional part which you can opt-in to use on specific parts. Configscript is something "outside" of the groovy files. And that immediately makes things more problematic: this option needs to be part of any compile stage, in any build, and the IDEs. Anway, I just wanted to chip in an opinion from a fan - but based on the reactions, it doesn't really seem like it will happen! Hey, this literally just hit me when about to hit "Add comment": *What about a different file-ending for statically compiled groovy files?! "HelloWorld.groovys"!* > Consider statically typed/compiled as default for Groovy 3.0 > > > Key: GROOVY-8329 > URL: https://issues.apache.org/jira/browse/GROOVY-8329 > Project: Groovy > Issue Type: New Feature >Reporter: Endre Stølsvik > > Personally, I do not understand why anyone would ever want to drop typing > from JVM based languages (or in any other language, for that matter). Thus, I > only started using Groovy "for real" when I discovered the @CompileStatic > annotation, which really made everything great! > If I could choose, I'd go for statically typed by default, with > @DynamicCompile or somesuch as an annotation I could turn on for methods that > uses the XML parsing features etc. > To me, it seems like more and more people are realizing that statically typed > languages is the way to go, notice e.g. TypeScript, Facebook's retrofitting > of types onto PHP with Hack, and even PHP's own typing in PHP 7. > Now with Kotlin joining the fray of JVM-based languages, whose literally > first two words on the wepage is "statically typed", getting special support > in Spring, and - notably - getting full support in Gradle, I'd say that this > applies more than ever. If Groovy "looses Gradle" to Kotlin due to the > ability to get a statically typed build script (oh, the joy!), I believe > Groovy will have a much harder time attracting new users. Turning Groovy into > one of the statically typed JVM languages, instead of hampering users with > "everything is an Object"-based runtime resolution, will increase the appeal > of the language. > The 3.0 can be a great point to change this. It could of course be reverted > back to previous logic by some -D switch (would need support in IDEs too, I > guess), or by sticking some magic "whole-sale annotation" at the top of the > source file, or something like this. -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Created] (GROOVY-8334) Java 8 Date/Time type support in Groovy JDK
Joe Wolf created GROOVY-8334: Summary: Java 8 Date/Time type support in Groovy JDK Key: GROOVY-8334 URL: https://issues.apache.org/jira/browse/GROOVY-8334 Project: Groovy Issue Type: New Feature Components: groovy-jdk Reporter: Joe Wolf Provide Groovy JDK methods for the types in Java 8's java.time package, similar to the ones which exist for java.util.Date/Calendar. The [Goodtimes|https://github.com/bdkosher/goodtimes] API can be used as the inspiration for the added methods. -- This message was sent by Atlassian JIRA (v6.4.14#64029)