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)?
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
[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 '. –
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. –