netClassLoader - source und erklärung

Ist dieser NetworkClassLoader hilfreich oder überflüssiges Spielzeug ?

  • hilfreich - Echt super das Ding, kann man verwenden

    Abstimmungen: 0 0,0%
  • überflüssig - sowas gabs und gibt es schon, du hast das Rad neu erfunden

    Abstimmungen: 0 0,0%

  • Anzahl der Umfrageteilnehmer
    0
S

SE

moinsen ...
ich weiß ... in anderen foren würde dieser beitrag in die rubrik OFF-TOPIC / CODESCHNIPZEL fallen ... aber die gibts hier nich ... und ins grundlagen-subforum gehört es einfach nicht

mir ist in der beschriebung von java.lang.ClassLoader unter der teil mit dem NetworkClassLoader mal beim simplen durchlesen aufgefallen und da hab ich mir gedacht : das versuch ich mal ganz simpel zu implementieren

eigentlich also lösung für ein problem mit einem meiner projekte um gewissen klassen die sich ändern können nicht in ein jar packen zu müssen auf das ich kein update anwenden kann weil das jar durch java gesperrt wird ...

das ganze funktioniert auch etwas anders als der bekannte URLClassLoader ...
*wobei ich mal versucht habe mit einem URLClassLoader ein jar zu laden welches sich in dem aktuellen jar befindet ... also mithilfe von getResource ... das klappt aber nich ... kennt hier jemand n workaround ?*

kurze beschreibung der funktionsweise
bei der instanzierung des clients wird die server adresse übergeben auf der der sog. ClassServer läuft ... dann muss explizit die connect-methode aufgerufen werden damit sich der netClassLoader mit dem server verbindet ...
wenn man alle klassen geladen hat kann man disconnect anwenden um die verbindung zu trennen

wenn die verbindung erfolgreich hergestellt wurde kann man einfach loadClass anwenden *welche ja durchs extends ClassLoader verfügbar is* ... benötigte klassen werden automatisch mitgeladen *wenn nötig* ...

hier erstmal die source-codes

client
NetworkClassLoader.java
Java:
package mdgl.lib.netClassLoader.client;
import java.io.*;
import java.net.*;
public class NetworkClassLoader extends ClassLoader
{
	private String server;
	private int port;
	private Socket sock;
	private InputStream in;
	private PrintStream out;
	//construtor
	//@param server - Server-Adresse
	//@param port - Port
	public NetworkClassLoader(String server, int port) { this.server=server; this.port=port; }
	//connect-methode - verbindung zum server herstellen
	public void connect() throws Exception
	{
		sock=new Socket(server, port);
		in=sock.getInputStream();
		out=new PrintStream(sock.getOutputStream());
	}
	//disconnect-methode - verbindung zum server trennen
	//das senden des befehls "--ConDC" bewirkt auf der server-seite das beenden des verbindungs-threads
	public void disconnect() throws Exception
	{
		out.println("--ConDC");
		out.close();
		in.close();
		sock.close();
	}
	//überschriebene findClass(String name) - methode von java.lang.ClassLoader
	//nach beispiel der beschriebung von java.lang.ClassLoader
	//leicht modifiziert zum Exception-handling
	//da java.lang.ClassLoader.findClass(String) nichts throwed kann hier auch kein throw angehängt werden > führt zum compiler-fehler
	@Override
	public Class findClass(String name)
	{
		byte[] b;
		try { b=loadClassData(name); } catch(Exception e) { e.printStackTrace(); return (Class)null; }
		return defineClass(name, b, 0, b.length);
	}
	//private loadClassData-methode ...
	//1. senden des binary-class-name an den server
	//2. empfangen der länge der daten-größe
	//3. empfangen der daten-größe
	//4. empfangen der daten
	//5. returnen an findClass
	private byte[] loadClassData(String name) throws Exception
	{
		out.println(name);
		byte[] size=new byte[in.read()];
		in.read(size);
		int length=Integer.parseInt(new String(size), 16);
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		byte[] buf=new byte[8192];
		int br=0, count=0;
		while(count<length)
		{
			br=in.read(buf);
			baos.write(buf, 0, br);
			count+=br;
		}
		baos.close();
		return baos.toByteArray();
	}
}

server
ClassServer.java
Java:
package mdgl.lib.netClassLoader.server;
import java.io.*;
import java.net.*;
public class ClassServer extends Thread
{
	private String PATH;
	private ServerSocket ss;
	public static void main(String[] args) { (new ClassServer()).startUp(); }
	private ClassServer() { System.out.println("MDGL NetworkClassLoader - Server"); setPath(); }
	private void setPath()
	{
		PATH=this.getClass().getResource(this.getClass().getSimpleName()+".class").toString();
		PATH=PATH.substring(PATH.indexOf("/")+1, PATH.length());
		if(PATH.contains("!"))
			PATH=PATH.substring(0, PATH.indexOf("!"));
		PATH=PATH.substring(0, PATH.lastIndexOf("/")+1);
		PATH=PATH+"classes";
	}
	private void startUp()
	{
		System.out.println("STARTUP : STARTUP INIT");
		System.out.print("STARTUP : OPEN ServerSocket ... ");
		try
		{
			ss=new ServerSocket(7464);
		}
		catch(Exception e)
		{
			System.out.println("FAILED");
			System.out.println("FATAL ERROR : CANT OPEN SERVERSOCKET");
			System.out.println("SERVER ALLREADY STARTED / PORT BLOCKED");
			System.out.println(e.toString());
			System.out.println("STARTUP : FAILED");
			System.out.print("TERMINATED");
			System.exit(1);
		}
		System.out.println("OK");
		System.out.println("STARTUP : OK");
		this.start();
	}
	public void run()
	{
		while(true)
		{
			try
			{
				Socket cs=ss.accept();
				(new ConThread(cs, PATH)).start();
			}
			catch(Exception e) { }
		}
	}
}

ConThread.java
Java:
package mdgl.lib.netClassLoader.server;
import java.io.*;
import java.net.*;
import mdgl.lib.*;
class ConThread extends Thread
{
	private String PATH;
	private Socket cs;
	private BufferedReader in;
	private OutputStream out;
	protected ConThread(Socket cs, String PATH) { this.cs=cs; this.PATH=PATH; }
	public void run()
	{
		try
		{
			in=new BufferedReader(new InputStreamReader(cs.getInputStream()));
			out=cs.getOutputStream();
		}
		catch(Exception e) { try{ cs.close(); } catch(Exception ex) { } return; }
		String line="";
		while(true)
		{
			try
			{
				line=in.readLine();
				if(line.equals("--ConDC"))
					break;
				load(line);
			}
			catch(Exception e) { e.printStackTrace(); break; }
		}
		try
		{
			in.close();
			out.close();
			cs.close();
		}
		catch(Exception e) { }
		return;
	}
	private void load(String name) throws Exception
	{
		File file=new File(PATH, name);
		int length=(int)file.length();
		String size=Integer.toString(length, 16);
		out.write(size.length());
		out.write(size.getBytes());
		FileInputStream fis=new FileInputStream(file);
		int br=0;
		byte[] buf=new byte[8192];
		while((br=fis.read(buf))!=-1)
		{
			out.write(buf, 0, br);
		}
		fis.close();
		out.flush();
	}
}

der server-klassen müssen package-gebunden im entsprechenden unterverzeichnis liegen
*bei mir z.b. also .../mdgl/lib/netClassLoader/server/*
die ladbaren klassen müssen dann im unterverzeichnis classes liegen ...
die namen der class-files entsprechen deren binary-namen ... also z.b. mdgl.lib.ToolKit ... OHNE .class ...


wie gesagt ... es ist eine sehr einfach implementierung und für 10-20 klassen konzipiert ...
das ganze könnte man jetzt noch so erweitern das z.b. ganze jar-files geladen werden können *dann würd ich aber n URLClassLoader nehmen und das jar-file via HTTP-server zur verfügung stellen* oder oder oder ...

es soll nur erstmal ne zur-verfügung-stellung sein für die-jenigen die sowas implementieren wollen oder ne implementierung suchen ...
es ist nicht DIE und schon garnich DIE BESTE implementierung ... und ich weis auch nich ob es schon was von seiten sun *oder meinetwegen mitlerweile oracle* fertig in java gibt ... *wenn ja wäre n tipp mal super =)*

ich werde auch noch ne api-doc hochladen ... hab aber auf dem rechner hier grade nicht die möglichkeiten ...

hoffe ich kann irgendwem mit dem hier helfen ...
oder euch wenigstens damit nerven =P
 
Zurück