snapshot von einem thread
tufan
- java
hallo,
ich habe heute mit einem Java Problem zu kämpfen.
Folgende Situation:
Mein Programm soll verschiedene Sortieralgorithmen graphisch darstellen.
Sortieralgorithmen sollen nebenläufig ablaufen und es soll möglich sein, modular weitere Sortierallgorithmen hinzuzufügen.
Der Status des (sortierten) Arrays soll in einem vordefinierten Zeitintervall abgefragt und graphisch dargestellt werden.
Mein Problem resultiert daraus, dass ich die durch das Constructer-Object von Reflect erstellte Instanz der Sortiermodule nicht in mein Interface SortModule casten kann.
Dafür ist folgender Code zuständig:
Enumeration en = this.selectedAllgorithms.elements();
while(en.hasMoreElements())
{
String className = en.nextElement().toString();
String classPath = "pfad zur Klasse"+className;
CustomClassLoader ccl = new CustomClassLoader();
Class c = ccl.loadClass( classPath );
Constructor[] theConstructors = c.getConstructors();
Class[] parameterTypes = theConstructors[0].getParameterTypes();
Constructor cons = c.getConstructor(parameterTypes);
Object argumentsList[] = new Object[2];
argumentsList[0] = this;
argumentsList[1] = this.data;
Thread sm = (Thread)cons.newInstance(argumentsList); /* hier funktioniert der type cast in SortModule nicht: SortModule sm = (SortModule)cons.newInstance(argumentsList); )*/
sm.start();
}
da sm vom Typ Thread sein muss; kann ich die Variablen und Methoden meiner Sortierklasse nur über getField() und invoke() bekommen (wenn es andere Möglichkeiten gibt, bin ich froh, diese zu hören).
Ich habe jedoch keine Möglichkeit gefunden ein Integer Array zu erhalten (das Array, das sortiert werden soll; und von dem ich die Snapschüsse brauche).
Kontrollerklasse -- starts (mit dem obigen Code) --> BubbleSort (sortiert einwandfrei, in echtzeit kann ich auch eine sehr hübsche Animation darstellen.
Wie kann ich das ganze zeitversetzt visualisieren?
Ist es möglich, dass sm alle 300 ms irgendwie das Array an die Kontrollerklasse schmeisst (welche es fängt, und daraus ein Bild generiert)?
oder alle 300ms holt sich die Kontrollerklasse das Array vom sm?
Bin für Vorschläge dankbar.
Grüße aus Berlin,
tufi
Hallo,
Mein Programm soll verschiedene Sortieralgorithmen graphisch darstellen.
Sortieralgorithmen sollen nebenläufig ablaufen und es soll möglich sein, modular weitere Sortierallgorithmen hinzuzufügen.
Algorithmus schreibt man mit nur einem l. Oben schreibst du es zweimal
richtig. Danach immer falsch, auch im Quellcode.
- Für die Modularität setze ich ein eigenes ClassLoader ein.
Die URLClassLoader-Klasse hätte es evtl. auch getan. Aber ein eigener
ClassLoader schadet eigentlich auch nicht, sofern man keine Bugs
reinprogrammiert. :)
- Sortierallgorithmen müssen mein Interface SortModule implementieren
Klingt sinnvoll.
- und erweitern die Klasse Thread.
Könnte man die Start-Methode nicht auch mit in SortModule reinnehmen?
Ob die Klasse nun von Thread ableitet oder nur eine Start-Methode
anbietet, die dann vielleicht an einen Thread delegiert, ist doch
eigentlich egal.
Mein Problem resultiert daraus, dass ich die durch das Constructer-Object von Reflect erstellte Instanz der Sortiermodule nicht in mein Interface SortModule casten kann.
Warum nicht? Das sollte schon gehen.
Dafür ist folgender Code zuständig:
Enumeration en = this.selectedAllgorithms.elements();
Schau dir mal iterator() und Iterator an. Das ist die "modernere"
Methode des Java Collections Framework, das die Enumeration-Geschichte
ablösen sollte. Steht auch so im Javadoc der Enumeration-Klasse.
>
> while(en.hasMoreElements())
> {
[...]
>
> Object argumentsList[] = new Object[2];
> argumentsList[0] = this;
> argumentsList[1] = this.data;
> Thread sm = (Thread)cons.newInstance(argumentsList); /\* hier funktioniert der type cast in SortModule nicht: SortModule sm = (SortModule)cons.newInstance(argumentsList); )\*/
Keine Ahnung, wieso das nicht gehen soll. Es scheint für mich gültiger
Java-Code zu sein. Zumindest solange das zu instanzierende Objekt
tatsächlich das Interface "SortModule" implementiert. (Allerdings
habe ich es jetzt nicht ausprobiert.)
Was passiert, wenn du "sm" nachträglich nach "SortModule" castest?
Wie genau äußert sich das "funktioniert nicht" eigentlich? Welche
Fehlermeldung erscheint?
> Ich habe jedoch keine Möglichkeit gefunden ein Integer Array zu erhalten (das Array, das sortiert werden soll; und von dem ich die Snapschüsse brauche).
Aus der Javadoc-Doku von java.lang.reflect.Method.invoke():
"If the method completes normally, the value it returns is returned
to the caller of invoke; if the value has a primitive type, it is
first appropriately wrapped in an object. However, if the value has
the type of an array of a primitive type, the elements of the array
are not wrapped in objects; in other words, an array of primitive
type is returned."
> Wie kann ich das ganze zeitversetzt visualisieren?
> Ist es möglich, dass sm alle 300 ms irgendwie das Array an die Kontrollerklasse schmeisst (welche es fängt, und daraus ein Bild generiert)?
> oder alle 300ms holt sich die Kontrollerklasse das Array vom sm?
Letzteres würde nach meinem Verständnis mehr Sinn machen. Wieso sollte
die Sortier-Klasse wissen wie oft die GUI aktualisiert werden soll?
Nimm doch eine der Timer-Klassen, um den Zustand der Sortier-Klassen
kontinuierlich abzufragen. Für GUIs am besten javax.swing.Timer.
Gruß
Slyh
PS: Beim Durchlesen kam mir mein Posting etwas mürrisch vor. Falls dem
so sein sollte: Es ist nicht mürrisch. :-)
Hallo Slyh,
Algorithmus schreibt man mit nur einem l. Oben schreibst du es zweimal
richtig. Danach immer falsch, auch im Quellcode.
danke. künftig weiss ich es besser :-)
Die URLClassLoader-Klasse hätte es evtl. auch getan. Aber ein eigener
ClassLoader schadet eigentlich auch nicht, sofern man keine Bugs
reinprogrammiert. :)
hmm.. scheint bisjetzt gut zu laufen. Ausserdem kompiliert mein ClassLoader auch .java dateien, wenn es sein muss.
Könnte man die Start-Methode nicht auch mit in SortModule reinnehmen?
Ob die Klasse nun von Thread ableitet oder nur eine Start-Methode
anbietet, die dann vielleicht an einen Thread delegiert, ist doch
eigentlich egal.
SortModule ist ein interface. Ich könnte höchstens noch definieren, dass die abgeleiteten Klassen eine run() Methode haben sollen. Wäre aber IMHO nicht sinnvoll.
Schau dir mal iterator() und Iterator an. Das ist die "modernere"
Methode des Java Collections Framework, das die Enumeration-Geschichte
ablösen sollte. Steht auch so im Javadoc der Enumeration-Klasse.
wenn mir noch Zeit bleibt, werde ich auf Iterator umstellen. Danke für den Tipp.
Keine Ahnung, wieso das nicht gehen soll. Es scheint für mich gültiger
Java-Code zu sein. Zumindest solange das zu instanzierende Objekt
tatsächlich das Interface "SortModule" implementiert. (Allerdings
habe ich es jetzt nicht ausprobiert.)
eben, das war auch mein Problem. Ich habe auch keine Ahnung warum das nicht geht. Hat mich eine Menge nerven gekostet bisjetzt.
Was passiert, wenn du "sm" nachträglich nach "SortModule" castest?
Wie genau äußert sich das "funktioniert nicht" eigentlich? Welche
Fehlermeldung erscheint?
ClassCastException ist die Folge. Die Ausführung wird beendet.
Ich habe jedoch keine Möglichkeit gefunden ein Integer Array zu erhalten (das Array, das sortiert werden soll; und von dem ich die Snapschüsse brauche).
Aus der Javadoc-Doku von java.lang.reflect.Method.invoke():
"If the method completes normally, the value it returns is returned
to the caller of invoke; if the value has a primitive type, it is
first appropriately wrapped in an object. However, if the value has
the type of an array of a primitive type, the elements of the array
are not wrapped in objects; in other words, an array of primitive
type is returned."
jepp. Aber, ich hatte bis vor ein paar Stunden nicht die aktuellste Java Version. Da hat invoke immer nur "gewrapptes" Object zurückgeliefert.
Letzteres würde nach meinem Verständnis mehr Sinn machen. Wieso sollte
die Sortier-Klasse wissen wie oft die GUI aktualisiert werden soll?
Nimm doch eine der Timer-Klassen, um den Zustand der Sortier-Klassen
kontinuierlich abzufragen. Für GUIs am besten javax.swing.Timer.
hmm.. damit das möglich ist, muss ich das type-casting-Problem (s.o.)lösen.
PS:
Das Interface SortModule:
public interface SortModule {
public void swap (int idx1, int idx2);
public void draw(int index, int wert);
}
Grüsse aus Berlin
tufi.
hallo wieder,
Keine Ahnung, wieso das nicht gehen soll. Es scheint für mich gültiger
Java-Code zu sein. Zumindest solange das zu instanzierende Objekt
tatsächlich das Interface "SortModule" implementiert. (Allerdings
habe ich es jetzt nicht ausprobiert.)
Irgendwie kann ich meine abgeleiteten Klassen nicht casten; auch nicht, wenn ich deren Typ selber angebe. Selbst folgender Code liefert ein Exception:
BubleSort o = (BubleSort)cons.newInstance(argumentsList);
Exception in thread "Thread-2" java.lang.ClassCastException: ub4.util.BubbleSort cannot be cast to ub4.util.BubbleSort
at ub4.gui.Visualiser.run(Visualiser.java:140)
at java.lang.Thread.run(Unknown Source)
Warum kann ein "gewrapptes" BubbleSort nicht in ein BubleSort umgewandelt werden?
und warum funktioniert (Thread)cons.newInstance(argumentsList);
, wenn BubbleSort Thread erweitert?
Grüße aus Berlin,
tufi
Hallo,
BubleSort o = (BubleSort)cons.newInstance(argumentsList);
Exception in thread "Thread-2" java.lang.ClassCastException: ub4.util.BubbleSort cannot be cast to ub4.util.BubbleSort
at ub4.gui.Visualiser.run(Visualiser.java:140)
at java.lang.Thread.run(Unknown Source)
Daß du einmal BubleSort und ein BubbleSort schreibst, ist nur ein Fehler
in deinem Beispiel, nicht in deinem Code, ja?
> Warum kann ein "gewrapptes" BubbleSort nicht in ein BubleSort umgewandelt werden?
Das ist seltsam. Sehr seltsam. Kann es sein, daß dein ClassLoader vielleicht
doch nicht korrekt funktioniert?
Wird die BubbleSort-Klasse dynamisch kompiliert? Das könnte ein Problem
sein, weil die VM dadurch evtl. erkennt, daß es sich um zwei verschiedene
Klassen handelt. (Nur weil beide Klassen gleich heißen, müssen sie ja
nicht identisch sein.)
Aber so aus der Entfernung fällt es mir jetzt etwas schwer, den Fehler
genauer einzugrenzen.
Debugge doch mal deinen ClassLoader und schau nach, wo die ClassCastException
genau geworfen wird, also welche Vorbedingung nicht erfüllt wird, durch
die es zur ClassCastException kommt. Ich bin mir ziemlich sicher, daß
das Problem irgendwo beim dynamischen Kompilieren oder beim Klasse-
Laden liegt...
Gruß
Slyh
Hallo,
Debugge doch mal deinen ClassLoader und schau nach, wo die ClassCastException
genau geworfen wird, also welche Vorbedingung nicht erfüllt wird, durch
die es zur ClassCastException kommt.
Vergiss den obenstehenden Satz. Der ist ja mal sowas von falsch. :-)
Gruß
Slyh
hallo Slyh,
Daß du einmal BubleSort und ein BubbleSort schreibst, ist nur ein Fehler
in deinem Beispiel, nicht in deinem Code, ja?
jepp, nur ein Tippfehler in diesem Beispiel.
Das ist seltsam. Sehr seltsam. Kann es sein, daß dein ClassLoader vielleicht
doch nicht korrekt funktioniert?
Also für das Casting-Problem habe ich glaube ich eine Erklärung gefunden:
[zitat]
Identical classes loaded by different classloaders are considered to be different classes by the JVM [/zitat]
Es scheint, das Problem resultierte tatsächlich, auch wenn nur indirekt, aus meinem ClassLoader. Es fehlt mir aber immer noch die Möglichkeit, wie ich meine Instanz trotz allen casten kann.
Du hattest UrlClassLoader erwaehnt. Das werde ich ausprobieren, sobald ich Zuhause bin. Wenn es mit dem URLClassLoader klappt, dann bin ich sogar bereit, auf das dynamische kompilieren zu verzichten :)
Werde darüber nochmal berichten.
Grüße aus Berlin,
tufi
hallo,
Werde darüber nochmal berichten.
der URLClassLoader wirft ClassNotFoundException raus.
Und da mir die Zeit wegrennt, werde ich -im Moment- auf dessen Verwendung verzichten müssen.
Muss wohl, ohne direkten Zugriff auf die Klassenvariablen auskommen.
Danke für die Hilfe.
Grüße aus Berlin,
tufi