StackOverFlow - SocketTimeoutException

Status
Nicht offen für weitere Antworten.

phlox81

Mitglied
Nach dem mein Crawler nun lauffähig ist,
und sich auch nicht mehr verläuft, hab ich das nächste Problem,
und keinen blassen Schimmer woran es liegen könnte:

Code:
java.lang.StackOverflowError
	at java.net.SocketTimeoutException.<init>(Unknown Source)
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.io.FilterInputStream.read(Unknown Source)
	at java.io.PushbackInputStream.read(Unknown Source)
	at org.apache.commons.httpclient.HttpConnection.isStale(HttpConnection.java:533)
	at org.apache.commons.httpclient.HttpConnection.isOpen(HttpConnection.java:468)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:660)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:529)
	at HTTPGet.GetRequest(HTTPGet.java:25)
	at Crawler.crawl(Crawler.java:51)
	at Crawler.crawl(Crawler.java:98)
	at Crawler.crawl(Crawler.java:104)
^So sieht es aus, wenn ich in HTTPGet Request keinen Timeout setze, sondern dies global im Header
der Helfer klasse tue.

Code:
java.lang.StackOverflowError
	at java.lang.Exception.<init>(Unknown Source)
	at java.io.IOException.<init>(Unknown Source)
	at java.io.InterruptedIOException.<init>(Unknown Source)
	at java.net.SocketTimeoutException.<init>(Unknown Source)
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.io.FilterInputStream.read(Unknown Source)
	at java.io.PushbackInputStream.read(Unknown Source)
	at org.apache.commons.httpclient.HttpConnection.isStale(HttpConnection.java:533)
	at org.apache.commons.httpclient.HttpConnection.isOpen(HttpConnection.java:468)
	at org.apache.commons.httpclient.HttpMethodBase.processRequest(HttpMethodBase.java:2653)
	at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1093)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:675)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:529)
	at HTTPGet.GetRequest(HTTPGet.java:26)
	at Crawler.crawl(Crawler.java:51)
	at Crawler.crawl(Crawler.java:98)

^So siehts mit jeweiligem gesetzten Timeout aus.

Die Klasse in der das Ganze stattfindet sieht so aus:
Code:
public class HTTPGet
{
	HttpClient http; 
	public  HTTPGet(){
		http = new HttpClient();
		http.setState(new HttpState());
    	http.getHostConfiguration().setProxy("mmoproxy", 8080);
    	UsernamePasswordCredentials upc = new UsernamePasswordCredentials();
    	upc.setPassword("");
    	upc.setUserName("");
    	http.getState().setProxyCredentials(null,null ,upc);
	}
	public String GetRequest(String request){
		try
		{
			//if(http.getHttpConnectionManager().getConnection(http.getHostConfiguration()).isOpen())
			{
			http.setTimeout(10000);
		    	//http.getHostConfiguration().setProxy("mmoweb", 8080);
		    	HttpMethod method = new GetMethod(request);
		    	method.setDoAuthentication(true);
			http.executeMethod(method); 
			String str = method.getResponseBodyAsString();
			method.releaseConnection();
			return str;
			}
			//return "";
		}
		catch (Exception e)
		{
			System.out.print("GetRequest: "+e.toString());
		}
		return null;
	}
}

Ich muss dazu wohl sagen, das der Fehler erst nach einiger Zeit auftritt,
vorher läuft alles reibunglos. Erst ab einer bestimmten Tiefe bzw. Laufzeit
tritt der Fehler auf.

Hat jemand eine Idee woran es liegen könnte ?
Ist es vielleicht der Speicherverbrauch ?

Devil
 

Soren

Mitglied
Schau doch mal nach Endlosschleifen. Wenn du dort Speicher verbrauchst, kommst du schnell zu einem StackOverflow.
 

Soren

Mitglied
Prinzipiell könntest du auch mal den Speicher für die VM hochsetzen, aber das wird dann nur dazu führen, dass dein Programm etwas später abstürzt. Die VM rufst du dann so auf:
java -Xms256m -Xmx256m -XX:MaxPermSize=256m

Versuch möglichst viele Objekte die du nutzt nur einmal zu initialisieren und sie nicht ständig zu verwerfen und neue zu erzeugen. Das hilft meistens am besten.
 

phlox81

Mitglied
In Java gibts ja leider kein delete ;)

Lokale Variablen werden aber doch sofort nach der Funktion wieder gekillt, richtig ?
 

Bleiglanz

Gesperrter Benutzer
System.out.print("GetRequest: "+e.toString());

liest du das immer mit?

wenn die nämlich fliegt, wird ja uU die Connection nicht geschlossen
 

Soren

Mitglied
devil81 hat gesagt.:
In Java gibts ja leider kein delete ;)

Lokale Variablen werden aber doch sofort nach der Funktion wieder gekillt, richtig ?

Delete gibt's nicht, das tut alles der Garbage Collector für dich. Der läuft allerdings in einem separaten Thread und sucht nach benutzten Objekten, indem er den Referenzgraphen auf und abläuft; nicht erreichbare Objecte werden zu Löschung markiert. Wenn du zu schnell zu viele riesige Objekte erzeugst, hat er eventuell nicht genug Zeit. "Sofort" ist also etwas zu hoch gegriffen.

Ich hab mal ein Programm geschrieben, dass die Festplatte nach mp3 absucht, die Tags ausliest und alles in XML vermerkt: auch da kamen ne ganze Menge von temporären Objekten zusammen, die zwar nach Methodenaufruf "weg" waren, aber scheinbar das Programm trotzdem durch StackOverflows zu Absturz brachten. Durch Verringerung der temporären Objekte pro Suchzyklus habe ich das Problem gelöst. Vielleicht war's auch nur Glück!? :bae:
 

phlox81

Mitglied
Bleiglanz hat gesagt.:
System.out.print("GetRequest: "+e.toString());

liest du das immer mit?

wenn die nämlich fliegt, wird ja uU die Connection nicht geschlossen

Nein, die ist noch nie geflogen, aber danke für den Hinweis :)
 

phlox81

Mitglied
So, hab jetzt angefangen meinen Code zu optimieren, möglichst wenig
Lokale Objekte (bin das von C++ gewohnt :roll: ), einiges hab ich statisch gemacht,
und kann jetzt meine Testseite schon auf 4 facher Tiefe crawlern.
Bei 5 Facher Tiefe fliegt er allerdings immer noch raus wegen Stackoverflow,
sind auch ein paar mehr links :lol: (Logdatei 3fache tiefe = 7 Kb, 4 Fache 27 Kb, 5 fache bis Crash 52 kb).

Meine Crawl Funktion ist momentan noch rekursiv, würde es etwas bringen
sie iterativ zu machen ?
Welche Optimierungsmöglichkeiten gibt es noch ?

Devil
 

Bleiglanz

Gesperrter Benutzer
willst du eine Webseite "crawlen"?

a) schmeiss mal den konstruktor in HTTPGet weg und mach eine einzige statische Methode getPage, mir der du dir eine Page abholst und die alles innerhalb der Methode erledigt

b) machs iterativ, ich würde das eher so machen

seiteninhalt holen
alle Links extrahieren und in datenbank schreiben
in der datenbank ein feld "zuletzt_geholt" als Datetime
dann fertig

dann lässt du den crawler über diese datenbank laufen, holst dir alle seiten, extrahierst die links und schreibst sie wieder in die DB
und bist fertig

auf diese weise würde die Tabelle immer weiter anwachsen, du könntest ein Timeout setzten (und oder den lastModified Header mit abspeichern) und so gezielt "neu laden"

die crawl methode würde dann so aussehen [kannst du ja in eine endlosschleife packen...]
Code:
resultset = SELECT FROM links // ggf. mit WHERE
while(rs.next){
    hole seite
    extrahiere alle Links
    insert aller gefundenen links in die tabelle (mit zuletzt_geholt=NULL)
}
als "Seed" musst du initial natürlich mindestens eine URL in deine Tabelle einfügen
 

phlox81

Mitglied
Bleiglanz hat gesagt.:
willst du eine Webseite "crawlen"?

a) schmeiss mal den konstruktor in HTTPGet weg und mach eine einzige statische Methode getPage, mir der du dir eine Page abholst und die alles innerhalb der Methode erledigt

b) machs iterativ, ich würde das eher so machen

seiteninhalt holen
alle Links extrahieren und in datenbank schreiben
in der datenbank ein feld "zuletzt_geholt" als Datetime
dann fertig

dann lässt du den crawler über diese datenbank laufen, holst dir alle seiten, extrahierst die links und schreibst sie wieder in die DB
und bist fertig

auf diese weise würde die Tabelle immer weiter anwachsen, du könntest ein Timeout setzten (und oder den lastModified Header mit abspeichern) und so gezielt "neu laden"

die crawl methode würde dann so aussehen [kannst du ja in eine endlosschleife packen...]
Code:
resultset = SELECT FROM links // ggf. mit WHERE
while(rs.next){
    hole seite
    extrahiere alle Links
    insert aller gefundenen links in die tabelle (mit zuletzt_geholt=NULL)
}
als "Seed" musst du initial natürlich mindestens eine URL in deine Tabelle einfügen

Jein, ich schreibe einen WAP Crawler.
Momentan bau ich damit einen Baum auf und speicher darin die Links.
An eine DB hab ich noch nicht gedacht, wäre auch nicht die beste Lösung, da
ich nicht weis ob diese auf der Zielplattform dann zur Verfügung steht.

Devil
 

Bleiglanz

Gesperrter Benutzer
nimm eine embedded db wie z.B. HSQL

problem ist doch, dass du beim rekursiven crawlen u.U. einen RIESIGEN Baum aufbaust

wenn nur 10 Links auf jeder seite sind:

10 gefunden auf level 1
100 gefunden auf level 2
1000 gefunden auf level 3
10000 gefunden auf level 4

d.h. wenn du rekursiv im level 4 bist, dann würden ja 1000 Einträge auf dem Stack rumliegen, das ist irgendwie unschön...

BTW: was solln das crawlen bringen, wenn alles im speicher ist? musst du doch eh irgendwo abspeichern??
 

phlox81

Mitglied
Natürlich soll ich nicht nur Last generieren :lol:

Die Klasse Crawler besitzt eine variable Reporter,
welche über notify aufgerufen wird, und dann jeweils

das Ergebnis z.b. in eine Datei schreibt. (Es sind mehrere Reporter möglich).

Im übrigen hab ich nun die sache auf Iterativ umgeschrieben,
und das bringt schon mal einiges :D
Level 5 Macht er nun anstandslos.
Hm, 6 fach ist nun auch kein Problem(insgesamt 6592 Links), ich glaub die Rekursion in
Java ist ein absolutes DON'T *g*

Devil
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
C StackOverflow bei Rekursion Java Basics - Anfänger-Themen 7
K MergeSort Stackoverflow Java Basics - Anfänger-Themen 5
P Compiler-Fehler StackOverFlow Java Basics - Anfänger-Themen 4
C Klassen StackOverflow bei erster Nutzung von Klassen/Konstruktoren Java Basics - Anfänger-Themen 9
M StackOverflow Problem Java Basics - Anfänger-Themen 9
F Stackoverflow bei Quicksort Java Basics - Anfänger-Themen 2
L StackOverFlow, finde Grund nicht! Java Basics - Anfänger-Themen 5
O StackOverflow für Eingabewerte berechnen Java Basics - Anfänger-Themen 3
J Stackoverflow-Abbruchbedingung Java Basics - Anfänger-Themen 7
G StackOverflow Fehler Java Basics - Anfänger-Themen 3
Y stackoverflow fehler Java Basics - Anfänger-Themen 7
G Stackoverflow! Java Basics - Anfänger-Themen 14
S Stackoverflow Error Java Basics - Anfänger-Themen 5
G Parser liefert StackOverflow error Java Basics - Anfänger-Themen 6
C StackOverflow Error, objekte öfters erzeugen Java Basics - Anfänger-Themen 6
M StackOverFlow bei JOptionPane? Java Basics - Anfänger-Themen 23
H Löschen in einem binären Baum führt zu einem StackOverflow Java Basics - Anfänger-Themen 2
frau-u StackOverflow - woher kommt es? Java Basics - Anfänger-Themen 7
W Compiler-Fehler java.net.SocketTimeoutException: connect timed out Java Basics - Anfänger-Themen 6

Ähnliche Java Themen

Neue Themen


Oben