Java Classloading läuft extrem langsam?

7

Ich versuche, eine Java-.class-Datei dynamisch zu laden und durch Reflektion aufzurufen.

Ich habe eine Klasse namens Foo; Es hat einen leeren Konstruktor und hat eine Methode namens doit (), die ein String-Argument annimmt und einen String zurückgibt. Es kehrt auch die Zeichenfolge um.

Hier ist mein Code:

%Vor%

Wie erwartet, druckt "Hello World!". Es dauert jedoch ca. <30 Sekunden . Ich weiß, Reflektion ist langsam, aber ich erwarte, dass es 10 ms oder so ist.

Ich benutze Eclipse mit JRE 1.6.0_13 und ich verwende Windows Vista.

Was mache ich hier falsch?

Danke.

Bearbeiten: Ich habe den Code profiliert, und seine gesamte Zeit wird in der dritten Zeile (loadClass ()) verwendet. Alles andere passiert sofort.

Bearbeiten: Ich habe den Code in eine Schleife gelegt; die langsame Funktion wird irgendwie optimiert und dauert nur 30 Sekunden in der ersten Schleife.

Bearbeiten: Ich habe die Lösung gefunden.

Anstelle von:

URL url = new URL("file://C:/jtest/");

Ich habe es geändert zu:

URL url = new URL("file:/C:/jtest/");

Jetzt funktioniert es perfekt. Ich weiß nicht, warum es funktioniert, aber ich sehe nicht, wie ich (und 5 andere Leute) das übersehen hätte. Jetzt fühle ich mich dumm ..

    
Lucky 22.05.2009, 03:36
quelle

6 Antworten

5

Nach 30 Sekunden sollten Sie in der Lage sein, Ihren Code zu "profilieren" und genau zu sehen, wo das Problem liegt (beim Laden der Klasse? beim Erstellen der Instanz? beim Nachschlagen der Methode? etc?)

Da es 30 Sekunden dauert (und nicht etwas viel kleiner, in der Größenordnung von etwa 10 ms), können Sie einfach System.out.println(new Date()); zwischen jeder Zeile Ihres Codes verwenden.

Ich nehme an, Sie werden feststellen, dass die loader.loadClass (String) so lange dauert - und ich vermute, dass Sie entweder einen sehr langen Klassenpfad oder einen Klassenpfad haben, der eine Netzwerkressource irgendeiner Art enthält / p>     

Jared 22.05.2009, 03:46
quelle
6

Für Ihre Informationen: Vielleicht ein bisschen spät für dich, aber ich stolperte über das gleiche Problem und fand diesen Beitrag.

Es sieht so aus, als ob das // eine Remote-Suche erzwingt. Wenn Sie mit -verbose: class laufen, wird eine UnknownHostException geladen, die intern beim Laden der Klasse geworfen werden muss.

Ich habe Folgendes versucht:

URL url = neue URL ("file: // localhost / C: / jtest /");

und das funktioniert (fast) so schnell wie Ihre Single Slash-Lösung.

    
Bert.V 30.09.2009 09:09
quelle
5

Überprüfen Sie Ihren Standardklassenpfad. Vielleicht bezieht es sich auf eine nicht verfügbare Netzwerkfreigabe oder etwas ähnliches.

    
Erich Kitzmueller 22.05.2009 03:43
quelle
3

Es ist möglich, dass beim Erstellen der Instanz viele andere Klassen geladen werden, von denen einige statische Initialisierer haben, die lange dauern. Setzen Sie diesen Code in eine Schleife und sehen Sie, was die folgenden Objekt-Kreationen kosten.

Bearbeiten : Cool, basierend auf deinem Profiling klingt das so, als ob du der Ursache nahe kommst. Eine andere Sache zu berücksichtigen ist, wenn Sie Bibliotheken verwenden, die große Startkosten haben. Ich benutze iBatis, um unsere Interaktionen mit Oracle zu verwalten, und wenn es zuerst hochfährt, liest es eine Reihe von XML-Dateien ein und verarbeitet die Abfragemuster in ihnen. Es gibt eine bemerkbare Verzögerung. Es wäre interessant zu hören, was Sie herausgefunden haben, aber Sie könnten entscheiden, dass die einmalige Zeit tolerierbar ist.

    
Jim Ferrans 22.05.2009 03:52
quelle
2

Es ist nichts falsch mit Ihrem Code ... Ich konnte Ihr Programm in weniger als einer Sekunde kompilieren. Ich betreibe Java 1.6.11 auf Vista Business.

Vielleicht ist Ihre public string doit(string arg) -Methode, was so lange dauert. Können Sie versuchen, es ohne Reflektion aufzurufen, um zu sehen, ob es lange dauert? Versuchen Sie, doit() einfach den übergebenen Parameter zurückzugeben (anstatt die Zeichen umzukehren), um zu sehen, ob Ihr Umkehralgorithmus das verlangsamt.

    
Cuga 22.05.2009 03:45
quelle
2

Ist es möglich, dass Sie Foo in den Standard-CLASSPATH setzen, damit Sie einfach etwas wie:

verwenden können %Vor%

, wobei ClassLoaderTest die Klasse ist, in der Sie arbeiten. Oder, falls Sie nicht in einem statischen Kontext arbeiten:

%Vor%

Mit diesen beiden Möglichkeiten können Sie einen neuen Klassenlader instanziieren.

Aber ich weiß nicht, ob dir das helfen wird (du musst dich profilieren), und die Reflektion wird immer merklich langsamer sein. Das kommt nicht herum. Natürlich sollte es aus diesem und anderen Gründen minimal in der Produktion verwendet werden.

EDIT: Da loadClass die meiste Zeit beansprucht, könnte es sein, dass C: \ jtest überladen ist. Sie können versuchen, Foo.class in ein Verzeichnis zu legen und dieses als URL zu verwenden. Natürlich ist der Grund, warum es das zweite Mal schneller ist, dass Foo bereits geladen ist.

    
Matthew Flaschen 22.05.2009 03:57
quelle

Tags und Links