Details
-
Bug
-
Status: Closed
-
Critical
-
Resolution: Fixed
-
2.5.13, 3.0.7
-
None
-
None
Description
The following exception has been thrown by an application in production:
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)
I think the following test class reproduces the problem :
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() } }
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.
$ 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
But with groovy 2.5.13 or the last stable version 3.0.7 the second affectation failed :
$ 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)
In org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation the method castToBoolean() takes care of the null value in accordance with the Groovy truth:
public static boolean castToBoolean(Object object) { // null is always false if (object == null) { return false; }
but the method castToBoolean() is obviously never called by castToType() when the value is null because the first line of castToType is :
if (object == null) return null;
How can I deal with this behaviour? I guess I must stuck ith the old 2.5.5 ?
Attachments
Issue Links
- relates to
-
GROOVY-11371 unsafe conversion of array of reference type to an array of primitive type
- Closed