gpt4 book ai didi

grails - Groovy在list.find调用中提供NPE,但仅在一段时间后

转载 作者:行者123 更新时间:2023-12-02 13:53:30 24 4
gpt4 key购买 nike

我们有很多这样的代码

// semi-pseudo code
def result = someList.find { condition == true }

( someList可以为null,但在groovy中可以这样做,因为 null.find{…}可以正常工作。)

这行代码在grails Controller 的作用下运行,并在生产中部署到服务器。在一段时间(有时是几小时,有时甚至更长)之后,上述代码行将开始引发NullPointerException-一旦开始引发NPE,便始终引发NPE。

通过调试,我们证明了即使someList为null(直到我们得到看似随机的第一个NPE),它仍然可以正常工作……通过调试,我们能够获得更详细的stacktrace,表明Groovy的MetaClassRegistryImpl.java行中存在错误。 214。

我搜寻了所有可以想到的组合,以查看是否存在任何已知的Groovy错误,但没有发现任何有值(value)的东西。

(它使用的是Grails 1.3.7,因此是Groovy 1.7.8)

设置了JMeter脚本,以运行一系列站点交互,从而使此问题半可重复。该脚本将遍历50-100系列,然后开始出现错误-一旦出现错误,在将应用程序重新部署到服务器(Glassfish)之前,它始终是错误的。

通过常规代码进行跟踪,看起来像这样:
//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);
}

因此,看来NPE在 obj.getClass()上了-如果是这种情况,我就对 someList为null时的工作方式感到困惑(但这是一个单独的主题)。

FWIW,我们没有对 someList进行任何我们自己的类或实例级元类编码。

Groovy中是否存在错误,或者我们可能会做错什么以导致Groovy代码深处的(随机)NPE?

更新-

观察结果是 someList被设置为'java null'而不是'groovy null'( NullObject)。该对象通过 Controller Action 中的流来自于映射(流上下文)。
class SomeController {

def someActionFlow = {
action {

def someList = flow.someList

}
}
}

有问题的情况是从未设置flow.someList时,该值应始终为null(groovy null)。 flow只是一张 map ,因此与 flow.get('someList')相同

上面的代码适用于未知数量的迭代,然后开始返回“java null”而不是“groovy null”。

最佳答案

我要冒一个危险,那就是它取决于someList的创建方式。也就是说,如果它是在Groovy中创建的,

def someList = null

然后,Groovy将 NullObject分配给变量。但是,如果该值是从其他某些Java组件作为真实的Java null返回的,则它将抛出NPE。更进一步,Groovy / Java / JVM中可能进行了一些优化,其中调用站点缓存导致其始终返回NPE。

再说一次,这只是一个疯狂的猜测。

关于grails - Groovy在list.find调用中提供NPE,但仅在一段时间后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6866253/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com