2017-04-10 4 views
4

Ich teste eine benutzerdefinierte Eclipse-RCP-Anwendung. Diese Anwendung führt eine einfache Initialisierung durch und startet dann eine Reihe von Threads, die viele XML-Dateien im Arbeitsbereich analysieren.NullPointerExceptions von zufälligen Codezeilen

Ungefähr einmal in 1000 Ausführungen stürzt einer dieser Threads mit NullPointerException ab. Dies geschieht normalerweise in Xerces, manchmal in anderen Bibliotheken und manchmal in der Java-Standardbibliothek. Das Problem ist, dass NullPointerExceptions in Zeilen auftreten, in denen kein Zeiger dereferenziert wird. Zum Beispiel:

java.lang.NullPointerException 
    at java.util.concurrent.locks.ReentrantReadWriteLock$Sync$HoldCounter.<init>(ReentrantReadWriteLock.java:279) 
    at java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter.initialValue(ReentrantReadWriteLock.java:289) 
    at java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter.initialValue(ReentrantReadWriteLock.java:286) 
    at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:180) 
    at java.lang.ThreadLocal.get(ThreadLocal.java:170) 
    at java.util.concurrent.locks.ReentrantReadWriteLock$Sync.tryAcquireShared(ReentrantReadWriteLock.java:481) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireShared(AbstractQueuedSynchronizer.java:1282) 
    at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lock(ReentrantReadWriteLock.java:727) 
    at org.eclipse.osgi.container.ModuleDatabase.readLock(ModuleDatabase.java:744) 
    at org.eclipse.osgi.container.ModuleDatabase.getWiring(ModuleDatabase.java:431) 
    at org.eclipse.osgi.container.ModuleContainer.getWiring(ModuleContainer.java:398) 
    at org.eclipse.osgi.container.ModuleRevision.getWiring(ModuleRevision.java:137) 
    at org.eclipse.osgi.container.ModuleWire.getProviderWiring(ModuleWire.java:51) 
    at org.eclipse.osgi.internal.loader.BundleLoader.findRequiredSource(BundleLoader.java:1114) 
    at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:392) 
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:352) 
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:344) 
    at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:160) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
    at org.eclipse.core.internal.resources.ProjectContentTypes.usesContentTypePreferences(ProjectContentTypes.java:116) 
    at org.eclipse.core.internal.resources.ContentDescriptionManager.getDescriptionFor(ContentDescriptionManager.java:321) 
    at org.eclipse.core.internal.resources.File.getContentDescription(File.java:255) 
    at my_app.ModelParser.getContentType(ModelParser.java:54) 
    at my_app.ModelParser.parse(ModelParser.java:43) 
    at my_app.ValidationModelsCache.getModel(ValidationModelsCache.java:44) 
    at my_app.BuilderContext.getParseResult(BuilderContext.java:37) 
    at my_app.ValidationHandler.validate(ValidationHandler.java:37) 
    at my_app.ProjectValidationBuilder$1.run(ProjectValidationBuilder.java:57) 
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55) 

Nichts kann null in Zeile 279. In der Tat sein, es nicht ein einziger dereferenzieren in der ganzen Methode ist:

276: static final class HoldCounter { 
277:  int count = 0; 
278:  // Use id, not reference, to avoid garbage retention 
279:  final long tid = getThreadId(Thread.currentThread()); 
280: } 

Ich habe doppelt und dreifach überprüfe ich das Recht habe, Quellen. Ich habe sogar einige dieser Methoden demontiert und es scheint dort keine Möglichkeit zu geben, dass null dereferenziert wird.

Hier ist ein weiteres Beispiel:

Caused by: java.lang.NullPointerException 
    at com.google.common.collect.ObjectArrays.checkElementsNotNull(ObjectArrays.java:233) 
    at com.google.common.collect.ObjectArrays.checkElementsNotNull(ObjectArrays.java:226) 
    at com.google.common.collect.ImmutableList.construct(ImmutableList.java:303) 
    at com.google.common.collect.ImmutableList.of(ImmutableList.java:98) 
    at com.google.common.collect.Iterables.concat(Iterables.java:432) 

Linie 233 ist nur eine return-Anweisung:

229:  static Object[] checkElementsNotNull(Object[] array, int length) { 
230:   for (int i = 0; i < length; i++) { 
231:    checkElementNotNull(array[i], i); 
232:   } 
233:   return array; 
234:  } 

scheint dies bisher nur auf einer Maschine geschehen:

CPU: Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz 
Linux: 4.9.0-2-amd64 #1 SMP Debian 4.9.18-1 (2017-03-30) x86_64 GNU/Linux 
Java: 
    openjdk version "1.8.0_121" 
    OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-4-b13) 
    OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode 

aber reproduziert auf ein paar verschiedenen Java- und Kernel-Versionen.

Was könnte dieses Verhalten verursachen, wie es zu debuggen?

Hat OpenJDK Option wie IBMs -Xdump, so kann ich Core-Dump erhalten, wenn problematische NullPointerException passiert?

Gibt es einen Trick, um gdb breakpoint auf NullPointerException zu setzen? Ich schätze jdb wird es nicht früh genug finden.

Könnte dies mit JVMs impliziten Nullprüfungen zusammenhängen? Gibt es ein Flag, um sie zu deaktivieren (-Xrs scheint nicht zu funktionieren)?

+4

279: letzte lange tid = getThreadId (Thread.currentThread()); kann null sein. Wenn getThreadId() einen Long-Wert zurückgibt, kann der zurückgegebene Wert null sein und eine NPE verursachen, wenn er versucht, ein primitives long zu analysieren. – Wietlol

+0

[getThreadId] (http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/80280d8b40e9/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java#l1492) gibt 'long 'zurück '. –

+0

Es kann sein, dass Ihre Stack-Spuren irgendwie verstümmelt sind, also hat die Spur, die Sie sehen, nichts mit dem Ort zu tun, der die Ausnahme erzeugt hat. –

Antwort

3

Was dieses Verhalten verursachen könnte

Instrumentierungsmittel, ein Hardware-Fehler oder SIGSEGV Signal irgendwie an den Prozess gesendet.

Does OpenJDK Option wie IBMs -Xdump hat, so kann ich bekommen Kern Dump, wenn problematische Nullpointer passiert?

-XX:AbortVMOnException=java.lang.NullPointerException, aber diese Option ist nur in non-product Builds verfügbar.

Gibt es einen Trick, um gdb breakpoint auf NullPointerException zu setzen?

Sie können versuchen, einen Haltepunkt an den folgenden Funktionen einstellen:

  • Runtime1::throw_null_pointer_exception(JavaThread*)
  • SharedRuntime::throw_NullPointerException(JavaThread*)
  • SharedRuntime::throw_NullPointerException_at_call(JavaThread*)

Obwohl eine Ausnahme von viel mehr verschiedenen geworfen werden kann setzt.

Eine bessere Möglichkeit besteht darin, JVM TI Callback einzurichten, das bei jeder ausgelösten Ausnahme aufgerufen wird. Hier ist an example des JVM TI-Agenten, der Ausnahmen abfängt.

Könnte dies mit JVMs impliziten Nullprüfungen zusammenhängen? Gibt es eine Flagge , um sie zu deaktivieren

Dies ist wahrscheinlich im Zusammenhang. Implizite Nullprüfungen können von -XX:-ImplicitNullChecks deaktiviert werden, aber das Flag ist wieder nur in Debug-Builds von JVM verfügbar.

+0

Ich habe immer noch Abstürze mit '-XX: -ImplicitNullChecks'. Ich kann dies nur auf optimierte OpenJDK-Builds reproduzieren. Es passiert nicht auf Debug oder OracleJDK. Ich habe es geschafft, einen Core-Dump mit leicht modifizierten '-XX: AbortVMOnException' zu bekommen. Wenn in gdb untersucht, sieht wie legitime NPE aus. Ich konnte keine der Hotspot-Tools zur Arbeit bringen. Endlich aufgegeben und meine App nicht mehr in dieser exakten Konfiguration laufen zu lassen. –