2016-05-23 10 views
5

これを開始する方法がわかりません。私はばかばかしいNullPointerExceptionがあるべきではない場所にある。状況は異常のように見えるので、私は答えからあまり期待していませんが、質問と答え(私が最終的に見つけたら)は教育目的に役立つかもしれません。そうでない場合は、おそらく質問を削除します。最初readonly変数で最終フィールドにアクセスすると奇妙なNullPointerExceptionが発生する

Caused by: java.lang.NullPointerException 
     at com.ah.dao.hbase.Snapshotable.lock(Snapshotable.java:17) 
     at com.ah.pipeline.dump.DumpController.dump(DumpController.java:78) 

07: public abstract class Snapshotable { 
08: private final AtomicBoolean readonly = new AtomicBoolean(false); 
09: 
10: abstract public TableSuit getTableInfo(); 
11: 
12: public boolean locked() { 
13:  return readonly.get(); 
14: } 
15: 
16: public final void lock() { 
17:  readonly.set(true); <-- happens here 
18: } 
19: 
20: public final void release() { 
21:  readonly.set(false); 
22: } 
23: } 

決勝ではなかったので、それは危険な出版効果かもしれない私が、今は何のアイデアを持っていません。これらの変数にはコード内のリフレクトトリックはありませんが、このクラスの子孫のいくつかのメソッドはaspectjでプロキシされています。 AOPの詳細

@Service 
public class HDao extends Snapshotable { 

    @PerformanceMonitoring 
    public void save(PatchEvent patchEvent) { 
     if (locked()) { 
      throw new DumpException(tableName); 
     } 

@Aspect 
@Component 
public class PMAdvice { 

    @Around(value = "@annotation(performanceMonitoring)", argNames = "jp, p") 
    public Object saveEvent(ProceedingJoinPoint jp, PerformanceMonitoring p) throws Throwable { 
     // basic stuff 
+0

あなたが投稿したコードに何かがないと仮定して、私は通常、そのようなNullPointerExceptionが発生したときに、自動的にunboxingするnull値を探します。 – EasterBunnyBugSmasher

+1

_ **しかし、このクラスの子孫のいくつかのメソッドはaspectj **でプロキシされています_それはどこかにあります。それなしでは伝えられない。 –

+0

あなたは逆コンパイルされたaspectクラスを見てみることができます(私はhttps://eclipse.org/aspectj/doc/released/pdguide/ltwdump.html#ltwdump-あなたがltwを使うと仮定します)。実行時プロキシは、 stacktraceとまた最終的な方法について文句を言う) – zapl

答えて

1


アップデートは、私は小さなプログラムでそれを再現することができます。 AOPには本当に問題がありました。デバッグの助けを借りて、私は最終的なメソッドがAspectJプロキシで動作しないことを発見しました。

AspectJでのプロキシ処理は、ランタイムサブクラス化によって行われることが判明しました。したがって、すべてのメソッドを代理オブジェクトに委譲するラッパー・サブクラスを作成します。 最終的な方法では問題ありません。

簡略化した例:

class WrapperProxy extends MyClass { 
    private MyClass delegate = new MyClass(); 

    @Override 
    public void run() { 
     delegate.run(); 
    } 
} 

この技術は、それらがサブクラスでオーバーライドすることができないため、最終的な方法に問題があります。 AspectJはそれを妙な方法で処理します。MyClassの別のデリゲートインスタンスを作成し、すべての最終メソッド呼び出しをそのインスタンスにリダイレクトします。このデリゲートは初期化されていませんし、私の場合は最終フィールドがnullです。

特定の問題を解決するために、メソッドから最終的なキーワードを削除しました。

+0

私はそれがもっと失敗に速いことを望みます。 AspectJが最終的なメソッドでクラスをサブクラス化しようとすると、私はエラーに感謝します。 – EasterBunnyBugSmasher

+0

@EasterBunnyBugSmasher技術的には起動時に警告が表示されます。問題はそれが春3でうまくいき、春4で壊れてしまったことです – AdamSkywalker

関連する問題