Compiler-Fehler Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 125, Size: 125

VirtualIndex

Aktives Mitglied
Ich erhalte die folgende Fehlermeldung:

Java:
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 125, Size: 125
    at java.util.ArrayList.rangeCheck(ArrayList.java:653)
    at java.util.ArrayList.get(ArrayList.java:429)
    at Client.getNewsHeadlines(Client.java:140)
    at Client$1.actionPerformed(Client.java:67)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6535)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6300)
    at java.awt.Container.processEvent(Container.java:2236)
    at java.awt.Component.dispatchEventImpl(Component.java:4891)
    at java.awt.Container.dispatchEventImpl(Container.java:2294)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
    at java.awt.Container.dispatchEventImpl(Container.java:2280)
    at java.awt.Window.dispatchEventImpl(Window.java:2750)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.awt.EventQueue$4.run(EventQueue.java:729)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Die betroffene Stelle ist diese:

Java:
    public void getNewsHeadlines(String link) throws IOException {
        Document doc = Jsoup.connect(link).get();
        Elements newsHeadlines = doc.select("a[href][title]");
        int length = newsHeadlines.size();
        for(int i = 0;i<length;++i) {
            if(!newsHeadlines.get(i).hasText()) {
                newsHeadlines.remove(i);
            }
        }
        System.out.println(newsHeadlines.size());
        newsHeadlines.trimToSize();
        System.out.println(newsHeadlines.size());
    }

Die ArrayListe newsHeadlines wird beim Programmstart deklariert und in dieser Methode zum ersten Mal initialisiert. Ich verstehe leider nicht ganz, warum hier eine IndexOutOfBoundsException geworfen wird. Zum Probieren habe ich die Variable length um mehrere Werte verkleinert, aber das Ergebnis bleibt das Gleiche. Woran liegt das?
 
Du nimmst die Größe der ArrayList als Wert für "length".
Und gehst eine for-Schleife so oft durch wie length groß ist.
In der Schleife entfernst du dann einfach Elemente (die Liste wird kleiner) aber du erhöhst dein "i" ganz normal weiter. Wenn du ein Element aus der Liste entfernst dann musst du "i" wieder um 1 reduzieren.
 
Beim Iterieren über eine Collection und dann auch noch Veränderung durchführen, können zu unverhersehbaren Problemen (so wie deine) führen. Der "way to go" ist hier einen Iterator zu nutzen.
Java:
for(Iterator<Element> iter = newHeadlines.iterator(); iter.hasNext();) {
	Element element = iter.next();
	if(element.hasText()) {
		iter.remove();
	}
}
 
Falls ja, dann versuch mal newsHeadlines nur bis length-1 zu durchlaufen

Das klappt leider nicht.

Beim Iterieren über eine Collection und dann auch noch Veränderung durchführen, können zu unverhersehbaren Problemen (so wie deine) führen. Der "way to go" ist hier einen Iterator zu nutzen.

Das hatte ich schon probiert, nur minimal anders. Dein Weg führt zu einer NullPointerException, die in einer anderen (später aufgerufenen) Methode liegt. Ich werde diese also überarbeiten müssen und dann geht es vermutlich. Der Grund dafür dürfte sein, dass ich die Struktur dieser Methode vorher etwas anders hatte und sie nun weniger Speicher verbraucht.

Danke euch!
 
Zuletzt bearbeitet:
Ich sitze im Moment an der Überarbeitung dieser Methode:

Java:
  public void removeItemsbyBadWords() {
     String[] arrBadWords = settings.getBadWords();
     for (int i = 0; i < arrBadWords.length; ++i) {
       String filter = ":contains(" + arrBadWords[i] + ")";
       Elements ele = newsHeadlines.select(filter);
       if (ele != null && ele.size() > 0) {
         for (Iterator<Element> iter = ele.iterator(); iter.hasNext();) {
           iter.remove();
         }
       }
     }
   }

Erneut ist es eine NPE:

Java:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at Client.removeItemsbyBadWords(Client.java:149)
    at Client$1.actionPerformed(Client.java:68)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6535)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6300)
    at java.awt.Container.processEvent(Container.java:2236)
    at java.awt.Component.dispatchEventImpl(Component.java:4891)
    at java.awt.Container.dispatchEventImpl(Container.java:2294)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
    at java.awt.Container.dispatchEventImpl(Container.java:2280)
    at java.awt.Window.dispatchEventImpl(Window.java:2750)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.awt.EventQueue$4.run(EventQueue.java:729)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Dumping Java heap ... done.

Was ist hier das Problem? Beim Problem davor weiß ich nun wieso und habe es auch verstanden, aber hier scheint es einen anderen Grund zu haben, bloß mit den gleichen Symptomen. Diese Methode wird direkt nach dem Aufruf der Methode getNewsHeadlines ausgeführt.
 
Zuletzt bearbeitet:
Also die Variablen arrBadWords, das i der for-Schleife und filter werden korrekt initialisiert. Ab der Zeile
Java:
Elements ele =  newsHeadlines.select(filter);
stürzt das Programm. Wie die Objekte zu dem Zeitpunkt sind kann ich nicht herausfinden.

Laut FindBugs befindet sich dort eine NPE, weil es Situationen gibt, wo null als Wert zurückkommen kann. Das sollte ich aber durch meine if-Bedingung abfangen. Oder ist hier ein grober Gedankenfehler?

Java:
Bug: Read of unwritten field newsHeadlines in Client.removeItemsbyBadWords()
The program is dereferencing a field that does not seem to ever have a non-null value written to it. Unless the field is initialized via some mechanism not seen by the analysis, dereferencing this value will generate a null pointer exception.
Rank: Scary (8),
confidence: Normal

Pattern: NP_UNWRITTEN_FIELD

Type: NP,
Category: CORRECTNESS (Correctness)<hr size="1" />

XML output:
<BugInstance type="NP_UNWRITTEN_FIELD" priority="2" rank="8" abbrev="NP" category="CORRECTNESS" first="26"> <Class classname="Client"> <SourceLine classname="Client" sourcefile="Client.java" sourcepath="Client.java"/> </Class> <Method classname="Client" name="removeItemsbyBadWords" signature="()V" isStatic="false"> <SourceLine classname="Client" start="146" end="156" startBytecode="0" endBytecode="276" sourcefile="Client.java" sourcepath="Client.java"/> </Method> <Field classname="Client" name="newsHeadlines" signature="Lorg/jsoup/select/Elements;" isStatic="false"> <SourceLine classname="Client" sourcefile="Client.java" sourcepath="Client.java"/> </Field> <SourceLine classname="Client" start="149" end="149" startBytecode="44" endBytecode="44" sourcefile="Client.java" sourcepath="Client.java"/> <SourceLine classname="Client" start="149" end="149" startBytecode="44" endBytecode="44" sourcefile="Client.java" sourcepath="Client.java"/> </BugInstance> <hr size="1" />

At Client.java:[line 149]
In method Client.removeItemsbyBadWords()
Field Client.newsHeadlines
 
Zuletzt bearbeitet:
Wie flown schon gesagt hat, verwende den Debugger.
Gehe zu der Zeile die du gefunden hast, wo das Programm abstürzt, und kontrolliere welches der Objekte null ist. 😉

PS: Deine for-Schleife wird nicht ganz funktionieren, da fehlt ein ganz wichtiger Aufruf. So würdest du endlos probieren immer das selbe Element aus der Liste zu entfernen
 
Die for-Schleife ist defekt gewesen, zumindest in der hier geposteten Version.

Das eigentliche Problem war, dass in der hier geposteten getNewsHeadlines eine Methodenvariable definiert und initialisiert wird, statt wie gewollt die Klassenvariable initialisiert wird mit dem Ergebnis. Dadurch gab es die unerwarteten Fehler und das Debugging viel schwer, da die Inhalte da waren, aber in einer Variable, die nicht weitreichend genug sichtbar war.
 

Zurück
Oben