の期間の後に私たちは、nullの場合も、このGroovyはlist.find呼び出しでNPEを与えるだけの時間
// semi-pseudo code
def result = someList.find { condition == true }
(someList
のようなコードに何かの塊を持っているが、それは正常に動作グルーヴィーnull.find{…}
ようにokです。)
このコード行は、grailsコントローラのアクションで実行されており、本番環境ではサーバーにデプロイされています。ある期間(時には時には時間がかかることもある)の後、上記のコード行はNullPointerExceptionをスローし始めます。そして、NPEを投げ始めると常にNPEを投げます。
someListがnullの場合でも、デバッグを行うと、うまく動作することがわかりました。(最初のNPEがランダムになるまで)...デバッグでも、エラーが示された詳細スタックトレースをGroovy MetaClassRegistryImpl.javaライン214
私は、任意の既知のGroovyのバグがあるかどうかを確認するために私は考えることができるすべての組み合わせをグーグルが、値の何も見つからなかっました。
A JMeterのスクリプトは、この問題は半繰り返し可能になり、サイトの一連の相互作用を介して実行するように設定した(このようなGroovy 1.7.8、Grailsの1.3.7を使用しています)。スクリプトは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が深刻な原因になる可能性がありますか?
UPDATE-
観察はsomeList
'はJavaのnull' の代わりに 'グルービーヌル'(NullObject
)に設定されていることです。オブジェクトは...コントローラのアクションのフローを経由してマップ(フローコンテキスト)から来ている
class SomeController {
def someActionFlow = {
action {
def someList = flow.someList
}
}
}
問題の場合は、flow.someListが設定されていないとき、それは常にnull(グルーヴィーヌル)であるべきです。それは上記のコードは、反復の数が不明のため正常に動作して、代わりに「グルーヴィーヌル」の「Javaのヌル」を返す開始しflow.get('someList')
をやってと同じであるので、flow
はただのマップです。
をコミットする特定の状況下でのNPEを回避するために、受信機はnullチェックを追加するにはFWIW、 'DEF = someListを引き起こします?。 find {condition == true} 'は問題を解決します。したがって、安全なナビゲーション演算子が解決策であるように見えますが、GroovyのNullObjectに関するこの問題のためにリファクタリングする必要のある、すでに生産中のコードがたくさんあります。 –
関連:http://stackoverflow.com/questions/5472795/groovy-why-i-dont-get-a-nullpointerexception-in-this-case –