We have a chunk of code something like this
// semi-pseudo code
def result = someList.find { condition == true }
(someList
may be null, but that is ok in groovy as null.find{…}
works fine.)
This line of code is running in an action of a grails controller and deployed in production to a server. After a period of time (sometimes hours, sometimes longer) the above line of code will start throwing a NullPointerException — and once it starts throwing the NPE it always throws the NPE.
Through debugging we've proven that it works fine even when someList is null (up until we get the seemingly random first NPE)… also through debugging we were able to get a more detail stacktrace that indicated there error was in Groovy's MetaClassRegistryImpl.java line 214.
I've googled every combination I can think of to see if there are any known Groovy bugs but found nothing of value.
(It is using Grails 1.3.7, thus Groovy 1.7.8)
A JMeter script was setup to run through a series of site interactions that makes this problem semi-repeatable. The script will iterate through 50-100 series and then the error starts appearing - once the error appears it is always in error until the application is redeployed to the server (Glassfish).
Tracing through the groovy code it looks something like this:
//AbstractCallSite.java
public Object call(Object receiver, Object arg1) throws Throwable {
return call(receiver, ArrayUtil.createArray(arg1));
}
//PerInstancePojoMetaClassSite.java
public Object call(Object receiver, Object[] args) throws Throwable {
if (info.hasPerInstanceMetaClasses()) {
try {
return InvokerHelper.getMetaClass(receiver).invokeMethod(receiver, name, args);
} catch (GroovyRuntimeException gre) {
throw ScriptBytecodeAdapter.unwrap(gre);
}
} else {
return CallSiteArray.defaultCall(this, receiver, args);
}
}
//InvokerHelper.java
public static MetaClass getMetaClass(Object object) {
if (object instanceof GroovyObject)
return ((GroovyObject) object).getMetaClass();
else
return ((MetaClassRegistryImpl) GroovySystem.getMetaClassRegistry()).getMetaClass(object);
}
//MetaClassRegistryImpl.java
public MetaClass getMetaClass(Object obj) {
return ClassInfo.getClassInfo(obj.getClass()).getMetaClass(obj);
}
So it appears the NPE is on the obj.getClass()
— if that's the case I'm a little baffled how it ever works when someList
is null (but that is a separate topic).
FWIW, we are not doing any class or instance level meta-class coding of our own on someList
.
Is there a bug in Groovy or what could we possibly be doing wrong to cause a (random) NPE deep in Groovy code?
UPDATE—
The observation is that someList
is being set to a 'java null' instead of a 'groovy null' (NullObject
). The object is coming from a map (flow context) via a flow in a controller action...
class SomeController {
def someActionFlow = {
action {
def someList = flow.someList
}
}
}
The case in question is when flow.someList has never been set it should always be null (groovy null). flow
is just a map so it is the same as doing flow.get('someList')
The above code works fine for an unknown number of iterations and then starts returning 'java nulls' instead of 'groovy nulls'.