invalid header field mit URLClassLoader

Kai008

Erfahrenes Mitglied
Ich schreibe fürm privaten Einsatz einen Server und ein signiertes Applet. Das Applet bekommt vom Server ein Jar-File als serialisiertes byte-Array. Das Applet cached es auf die HDD und soll es dann von dort per URLClassLoader geladen werden. Die benötigten Klassen werden aus der Manifest gelesen, da es Klassen gibt die auf dem Applet-Clienten, dem Server und anderen Clienten die ein zusätzliches Programm, welches ich erst später schreibe laufen sollen.

Der MD5-Fingerprint am Clienten ist mit dem am Server ident, es ist zum Debugen auch eine Main in der Jar eingetragen, und direkt starten geht problemlos. Der Klassenpfad stimmt natürlich auch.

Java:
public Plugin(File f) throws InstantiationError, ZipException, IOException
{
	ZipFile zipFile = new ZipFile(f);
	InputStream inputStream = zipFile.getInputStream(META_INF);
	
	Pattern pattern = Pattern.compile("=");
	
	URLClassLoader classLoader = new URLClassLoader(new URL[] {
			f.toURI().toURL()
	});
	
	for(String line = null; (line = readLine(inputStream)) != null;)
	{
		if(line.contains("="))
		{
			String[] splittedLine = pattern.split(line, 0);
			if(splittedLine.length == 2)
			{
				if(splittedLine[0].equalsIgnoreCase("menuitemtext"))
					menuItemText = splittedLine[1];
				else if(splittedLine[0].equalsIgnoreCase("mainpanel"))
				{
					String panelPath = splittedLine[1];
					try
					{
						mainPanel = (JPanel) classLoader.loadClass(panelPath).newInstance();
					}
					catch (Throwable t)
					{
						t.printStackTrace();
						throw new InstantiationError();
					}
				}
			}
		}
	}
}

Code:
java.lang.ClassNotFoundException: pak.MainPanel
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at core.loginScreen.kernel.Plugin.<init>(Plugin.java:49)
	at core.loginScreen.kernel.LoadPluginsFromTemp.load(LoadPluginsFromTemp.java:28)
	at core.loginScreen.kernel.CreateKernel.create(CreateKernel.java:15)
	at core.loginScreen.LoginButton.run(LoginButton.java:68)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: invalid header field
	at java.util.jar.Attributes.read(Unknown Source)
	at java.util.jar.Manifest.read(Unknown Source)
	at java.util.jar.Manifest.<init>(Unknown Source)
	at java.util.jar.JarFile.getManifestFromReference(Unknown Source)
	at java.util.jar.JarFile.getManifest(Unknown Source)
	at sun.misc.URLClassPath$JarLoader$2.getManifest(Unknown Source)
	at java.net.URLClassLoader.defineClass(Unknown Source)
	at java.net.URLClassLoader.access$000(Unknown Source)
	... 10 more
Exception in thread "LoginButton" java.lang.InstantiationError
	at core.loginScreen.kernel.Plugin.<init>(Plugin.java:54)
	at core.loginScreen.kernel.LoadPluginsFromTemp.load(LoadPluginsFromTemp.java:28)
	at core.loginScreen.kernel.CreateKernel.create(CreateKernel.java:15)
	at core.loginScreen.LoginButton.run(LoginButton.java:68)
	at java.lang.Thread.run(Unknown Source)

Ich hoffe ihr könnt mir helfen, ich finde absolut nichts brauchbares darüber.
 
da ichs gelesen habe : das thema mit den dynamisch zu ladenen plugins hatten wir erst vor 2 tagen mal wieder von mir selber

http://www.tutorials.de/forum/java/357126-wieder-mal-java-und-plug-ins.html

zieh es dir rein ... vllt hilft es dir ...

was das laden der files über die server-app angeht .. : wenn ich nicht ganz daneben liege kann mit hilfe der ByteArray-streams und nem File-objekt auch ein file im RAM erzeugen wodurch ein cachen auf der platte und die dafür notwendige signierung entfällt *es sei denn du hast ein zertifikat welches du für geld von ner CA zertifizieren lassen hast ... dann würd ichs auf jeden fall trotzdem signieren ...*

zu deinem eigentlichen problem : ich werde aus deinem code da nicht ganz schlau ...
nach meiner auffassung *korrigieren mich bitte wenns falsch ist* möchtest du übern browser nur ein kleines applet laden welches sich über eine auf dem server laufende app die eigentlichen paket zieht , auf platte cached und diese dann plug-in mäßig läd ... oder liege ich daneben ?

in diesem fall sollte dir das code-beispiel von Thomas helfen ...

setze das ganze nur von nem mudolaren app-server in n client-applet um *geht mit einigen modifizierungen sogar binnen 5min*
und dann schreibst du halt einfach nur die package- und klassen-listings in die service-datei und läds dann zur runtime einfach mit nem URLClassLoader die daten und wendest den service-handler drauf an ...

nutz mal die sufu mit begriffen wie "plugin" oder lies dir die verlinkten posts durch ...
ich denke doch das du da auf eine praktikable lösung kommen solltest ...

ansonsten solltest du vllt mal etwas genauer das ablauf-prinzip erklären
 
Danke. Ich weiß, hab auf das Thema ja auch geantwortet, aber es dann wieder vergessen.
Das mit dem ByteArray-Stream wusste ich noch nicht. Ist auch eine gute Idee. Sonst wollte ich es einfach mit dem jarsigner aus dem SDK machen, ist ja nur für private Zwecke.
Ich habe ein kleines LAN, was ich auch manchmal für verteilte Rechenaufgaben benutze. Das alte Steuerprogramm war aber so ein Mist, dass ich es jetzt von Grund auf neu schreiben wollte.
Ich dachte mir das so: Das Applet liegt am Server auf dem ein Apache läuft. Dieser läd sich nach dem man die Benutzerdaten angegeben hat die Module herunter, und zeigt bis auf 4 statische JPanel's die in der Manifest geschriebenen Menüpunkte, und beim Klick die JPanel's davon an. Nach dem man die Einstellungen getroffen hat, generiert das JPanel eine Liste mit den Befehlen und sendet sie am Server. Ein Thread aus der JAR genieriert daraus Subjobs, die der Reihe nach in einen LILA-Stack kommen, und an die verbundenen Clienten gesand werden. Ein wieder anderer Thread bearbeitet sie, und sendet das Ergebniss zurück. Darauf bekommt er einen neuen Job.
Alle Ergebnisse werden in einer Klasseninstanz am Server gespeichert, und wenn alle Subjobs abgearbeitet werden, oder wenn er bereits zu dem benötigten Ergebniss gekommen ist wird das Ergebniss mit dem Job verlinkt, damit es der Server dem Applet mitteilen kann. Aber so weit am Ende habe ich mir nur Oberflächlich gedanken gemacht.

Hältst du das für keine gute Idee? So könnte ich ja bspw. auch einfach indem ich per Applet ein neues Modul hochlade dieses einbinden, da es bei der nächsten Verbindung automatisch mitgeladen wird.
 
oke .. ich glaube wir reden an ein ander vorbei ^^
laut titel hast du ja probleme mit dem URLClassLoad
dann deutet dein code im ersten post auf ein modulares system hin *ist ja nach deinem aktuellen post nicht weit davon entfernt ^^*
ich verstehe aber glaube ich immer noch nicht ganz welches ziel du hast ...
so wie ich es bis jetzt verstanden habe möchtest du also eine verteilte rechenlast erzeugen und ein applet als control-software für die server-app nutzen ...
dessweiteren willst dus modular halten ... daher auch deine fragen nach dem laden der JAR-files übers netzwerk ..
das applet würde dir nur ne möglichkeit bieten wenn du das ganze auch von außerhalb steuern willst ohne nervige setups ...
wenn du allerdings eine feste workstation hast würde ich das ganze als APP bauen ... die hat mehr rechte und es lässt sich wie gesagt das lästige immer wieder re-signen des applets vermeiden ...

was gernerell das verteilte rechnen angeht muss ich leider passen da ich mich mit diesem bereich der IT noch garnicht auseinandergesetz habe ...

wenn jetzt irgendwas in meinem post nicht dem entsprechen sollte was du vorhast bitte ich dich um nachsicht da auch ich geistig nicht mehr ganz auf der höhe bin zur zeit ...
vllt würde es leichter fallen wenn du ein kleines beispiel angibst was genau dein ziel ist und wie du das erreichte dann später nutzen willst ...
vllt gibt es auch so genies wie unseren Thomas der schon ausm ersten post schlau wird ... ich jedenfalls nicht ^^

in diesem sinne ... SPiKEe
 
Ich glaube du hast alles richtig verstanden. Na ja, nicht Lastenverteilung sondern High Performance, aber eigendlich eh Haarspalterei.
Du hast mich aber auf die Idee gebracht, statt dessen ein Applet zu schreiben, was nur Bilder von einem Programm am Server empfängt, und Tastendrücke/Mousebewegungen/klicks an diesen sendet und per Robot wiedergibt. Eben ein einfaches RDC. So könnte ich z. B. die Zugriffskontrolle dort einbauen, und das Steuerprogramm entschlaken, was das arbeiten daran auf Dauer wohl auch erleichtern wird. Zudem muss nicht so viel internes zwischen Server und Applet gequatscht werden, was es wohl auch einfacher macht.
Ich möchte dem Server ohne Monitor/Inputgeräte betreiben, da ich hier kaum Platz habe.

Du hast offensichtlich viel mehr Erfahrung/Ideeen in Realisierungsmöglichkeiten, hältst du es so für eine gute Idee?
 
Zurück