Java Klassen aus externer .jar laden und ausführen

  • Themenstarter Themenstarter Tom Schneider
  • Beginndatum Beginndatum
T

Tom Schneider

Gast
Hi,

ich arbeite gerade mal wieder an meinem Launcher und möchte eine Klasse aus einer anderen .jar Datei ausführen. Dass soll dann ungefähr vom ablauf her so aussehen:

Launcher.jar
||
||
===============> /home/user/.game/bin/game.jar

Dabei soll es nicht dringend notwendig sein, dass game.jar schon von anfag an existiert sondern es kann auch sein dass die datgei erst noch vom launcher heruntergeladen wird. ausserdem soll der launcher dem game mehrere variablen übergeben. ich habe es schon mit ClassLoadern und ProcessBuildern versucht. habe aber nie den richtigen ansatz gefunden. hat jemand einen rat für mich?

(gutes beispiel ist minecraft und der minecraft launcher)
 
Mit URLClassLoader warst du schon mal gar nicht so falsch. Ich persönlich verwende ihn bei meinem eigenen Projekt (ist schon weiter ausgereift : auto-download, -update, security, etc).

Die Verwendung ist eigentlich ganz einfach : du erstellst einen URLClassLoader dem du ein entsprechendes URL[]-Objekt übergibst. Dann callst du auf diesen URLClassLoader einfach loadClass("mein.package.Klasse") und bekommst ein Class<?> Object. Das kannst du dann entweder casten oder newInstance() drauf callen (wichtig hierfür : Klasse muss parameterlosen Standardkonstruktor PUBLIC implementieren).

In wie weit man hier mit einem Interface für ein Cast arbeiten sollte kann ich dir nicht verraten (habe da so meine ganz eigene Implementierung, schwer die jetzt zu erklären), wäre aber sicher eine gute Idee wenn du noch Parameter mitgeben willst.

Willst du aber ohne das gehampel mit Interfaces und Casts noch Parameter übergeben könntest du noch was mit Reflections machen. Du nimmst halt das Class<?>-Object und holst dir dann mit getDeclaredConstructors() ein Constructor<?>[]-Objekt. Diese Array kannst du durchgehen und dann mit den verschiedenen Methoden der Klasse Constructor den Richtigen Bestimmen (erübrigt sich natürlich wenn du nur einen Konstruktor hast oder über Class.getDeclaredConstructor(Class<?>...) dir gleich den entsprechenden besorgst).

Über Constructor.newInstance(Object...) kannst du dir dann eine Instanz mit den entsprechendne Parametern holen.


Klingt alles etwas komplizierter als es ist, aber glaub mir : einmal richtig implementiert wirst du sehen das es die Mühe wert war.
 
Java:
URL jarURL = new File("/home/tom/Arbeitsfläche/testopenframe.jar").toURL();
	     
	  
	     ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
	     if(classLoader != null && (classLoader instanceof URLClassLoader)){
	         URLClassLoader urlClassLoader = (URLClassLoader)classLoader;
	         Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
	         addURL.setAccessible(true);
	         addURL.invoke(urlClassLoader, new Object[]{jarURL});
	     }
	     
	     
	     Class testRunnerClass = classLoader.loadClass("net.miniframe.src.Main");
	    
	     String[] my1 = { "USERNAME", "MD5-SECURITYSUM" };
	     Object myarg1[] = { my1 };
	     testRunnerClass.getMethod("main", new Class[]{String[].class}).invoke(null, myarg1);

So habe ich es jetzt gelöst... kannst du mir dazu vielleicht noch ein paar Tipps geben? z.B. zum Thema sicherheit?

Tom
 
Auch wenn ich das schon öfter gesehen habe bin ich kein Fan davon :
Ich meinte mit Reflection eigentlich NICHT das du den SystemClassLoader manipulieren sollst sondern nur ne Möglichkeit des invokens.

Erzeuge einfach eine eigene neue Instanz von URLClassLoader und arbeite mit diesem.

Was Sicherheit angeht : da du ja nur main(String[]) callst kannst du eigentlich auch dierekt mit Process arbeiten. Da gibt es nicht viel zu sagen. Wenn du jetzt wie ich mehrere "Plugins" laden würdest wo auch Dritte ihren Code einschleusen können wäre es was anderes.
 

Neue Themen


Zurück
Oben