You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Eric Milles (Jira)" <ji...@apache.org> on 2021/03/03 03:16:00 UTC

[jira] [Updated] (GROOVY-9916) IllegalArgumentException when set null to a boolean field into a closure

     [ https://issues.apache.org/jira/browse/GROOVY-9916?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Eric Milles updated GROOVY-9916:
--------------------------------
    Fix Version/s: 3.0.8

> IllegalArgumentException when set null to a boolean field into a closure
> ------------------------------------------------------------------------
>
>                 Key: GROOVY-9916
>                 URL: https://issues.apache.org/jira/browse/GROOVY-9916
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 2.5.13, 3.0.7
>            Reporter: Eric Vernier
>            Assignee: Eric Milles
>            Priority: Critical
>             Fix For: 3.0.8, 4.0.0-alpha-3
>
>          Time Spent: 0.5h
>  Remaining Estimate: 0h
>
> The following exception has been thrown by an application in production:
> {code}
> Caused by: java.lang.IllegalArgumentException: Can not set boolean field c.c.a.a.b.t.b.save.RestoreDataMssqlTask.schemaExistInBackup to null value
> 	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
> 	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
> 	at sun.reflect.UnsafeBooleanFieldAccessorImpl.set(UnsafeBooleanFieldAccessorImpl.java:80)
> 	at java.lang.reflect.Field.set(Field.java:764)
> 	at org.codehaus.groovy.reflection.CachedField.setProperty(CachedField.java:76)
> 	at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:2718)
> 	at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:3809)
> 	at c.c.a.a.b.t.b.save.AbstractRestoreTask.setProperty(AbstractRestoreTask.groovy)
> 	at org.codehaus.groovy.runtime.InvokerHelper.setProperty(InvokerHelper.java:213)
> 	at groovy.lang.Closure.setPropertyTryThese(Closure.java:370)
> 	at groovy.lang.Closure.setPropertyOwnerFirst(Closure.java:364)
> 	at groovy.lang.Closure.setProperty(Closure.java:353)
> 	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.setGroovyObjectProperty(ScriptBytecodeAdapter.java:544)
> 	at c.c.a.a.b.t.b.save.RestoreDataMssqlTask$_execImportDatasource_closure1.doCall(RestoreDataMssqlTask.groovy:86)
> {code}
> I think the following test class reproduces the problem :
> {code:groovy}
> class Test {
> 	private boolean b
> 	
> 	static final void main(String... args) {
> 		new Test().f()
> 	}
> 	
> 	def f() {
> 		println('set boolean to null')
> 		b = null
> 		def closure = { 
> 			println('set boolean to null inside a closure')
> 			b = null
> 		}
> 		closure()
> 	}	
> }
> {code}
> The conditions are 1) affect null to a primitive boolean variable, 2) the variable must be an instance field, 3) the affectation must be executed in a closure
> With Groovy 2.5.5 no exception.
> {code}
> $ groovy -version
> Groovy Version: 2.5.5 JVM: 1.8.0_265 Vendor: AdoptOpenJDK OS: Windows 10
> $ groovy Test
> set boolean to null
> set boolean to null inside a closure
> {code}
> But with groovy 2.5.13 or the last stable version 3.0.7 the second affectation failed :
> {code}
> $ groovy -version
> Groovy Version: 3.0.7 JVM: 1.8.0_265 Vendor: AdoptOpenJDK OS: Windows 10
> $ groovy Test
> set boolean to null
> set boolean to null inside a closure
> Caught: java.lang.IllegalArgumentException: Can not set boolean field Test.b to null value
> java.lang.IllegalArgumentException: Can not set boolean field Test.b to null value
>         at Test$_f_closure1.doCall(Test.groovy:14)
>         at Test$_f_closure1.doCall(Test.groovy)
>         at Test.f(Test.groovy:16)
>         at Test$f.call(Unknown Source)
>         at Test.main(Test.groovy:6)
> {code}
> In {{org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation}} the method [castToBoolean()|https://github.com/apache/groovy/blob/ac852d6a53bcb583849cb8db8a1cbede5b097502/src/main/java/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java#L185] takes care of the {{null}} value in accordance with the Groovy truth:
> {code:java}
> public static boolean castToBoolean(Object object) {
>         // null is always false
>         if (object == null) {
>             return false;
>         }
> {code}
> but the method {{castToBoolean()}} is obviously  never called by [castToType()|https://github.com/apache/groovy/blob/ac852d6a53bcb583849cb8db8a1cbede5b097502/src/main/java/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java#L218] when the value is null because the first line of castToType is :
> {code:java}
> if (object == null) return null;
> {code}
> How can I deal with this behaviour? I guess I must stuck ith the old 2.5.5 ?



--
This message was sent by Atlassian Jira
(v8.3.4#803005)