2016-05-23 11 views
5

Ich bin mir nicht sicher, wie ich das anfangen soll. Ich habe lächerlich NullPointerException an einem Ort, wo es nicht sein sollte. Ich erwarte von den Antworten nicht viel, da die Situation wie eine Anomalie aussieht, aber die Frage und die Antwort (wenn ich schließlich eine finde) können für Bildungszwecke nützlich sein. Wenn es nicht ist, werde ich wahrscheinlich die Frage löschen.Weird NullPointerException beim Zugriff auf das letzte Feld

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: } 

Zuerst readonly Variable war nicht endgültig, so dass ich, obwohl es eine unsichere Veröffentlichung Wirkung sein könnte, aber jetzt habe ich keine Ideen. Es gibt keine Reflektionstricks mit diesen Variablen in unserem Code, aber einige Methoden dieser Klasse werden mit aspectj umgangen.


Aktualisierung mit AOP Details

@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

unter der Annahme, dass etwas in dem Code fehlt, den Sie veröffentlicht haben, suche ich normalerweise nach Null-Werten, wenn ich eine solche NullPointerException bekomme. – EasterBunnyBugSmasher

+1

_ ** aber einige Methoden dieser Klasse Nachkommen sind mit aspectj ** _ Proxy Es ist alles da drin. Kann nicht ohne es sagen. –

+0

Sie könnten versuchen, sich die dekompilierten Seitenklassen anzuschauen (ich denke, https://eclipse.org/aspectj/doc/released/pdguide/ltwdump.html#ltwdump- vorausgesetzt, Sie verwenden ltw. Runtime-Proxies sollten in der erscheinen Stacktrace und beschweren sich über endgültige Methoden) – zapl

Antwort

1

Ich könnte das mit einem kleinen Programm reproduzieren. Das Problem war tatsächlich mit AOP verbunden. Mit Hilfe des Debugging habe ich festgestellt, dass die finalen Methoden nicht mit AspectJ Proxying funktionieren.

Es stellte sich heraus, dass Proxying in AspectJ durch Runtime Subclassing durchgeführt wird. So wird eine Wrapper-Unterklasse erstellt, die alle Methoden an Proxy-Objekte delegiert. Es funktioniert gut für nicht endgültige Methoden.

vereinfachtes Beispiel:

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

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

Diese Technik hat ein Problem mit dem letzten Methoden, da sie nicht in Unterklassen außer Kraft gesetzt werden. AspectJ behandelt es auf seltsame Weise: Es erstellt eine andere Delegat-Instanz von MyClass und leitet alle letzten Methodenaufrufe dorthin um. Dieser Delegat ist noch nicht initialisiert und in meinem Fall hatte er Null-Endfelder.

Um mein spezielles Problem zu beheben, habe ich nur ein endgültiges Schlüsselwort aus Methoden entfernt.

+0

lässt mich wünschen, dass war mehr Fail-Fast. Ich würde einen Fehler schätzen, wenn AspectJ versucht, eine Klasse mit finalen Methoden abzuleiten. – EasterBunnyBugSmasher

+0

@EasterBunnyBugSmasher technisch gibt es eine Warnung beim Start. Das Problem ist, dass es im Frühling 3 gut funktioniert hat und im Frühling 4 gebrochen wurde – AdamSkywalker

Verwandte Themen