Classpath mit ClassLoader künstlich erweitern

Niklaus Bucher

Grünschnabel
Hallo

ist es möglich, den ClassPath per Classloader irgendwie künstlich zu erweitern? Grund dafür ist, dass ich die jars die API nicht wegkopieren kann und die Zeichenlänge des ClassPaths beschränkt ist.

Ich würde mir das inetwa so vorstellen:

Code:
import java.util.ArrayList;
import java.util.Iterator;

public final class MyClassLoader extends ClassLoader {
    MyClassLoader() {
	ArrayList jars = new ArrayList();
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/agenda.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/aportisdoc.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/bsh.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/classes.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/commonwizards.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/fax.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/form.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/hsqldb.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/java_uno.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/java_uno_accessbridge.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/js.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/juh.jar");
	jars.add("C:/Programme/OpenOffice.org 2.3/program/classes/jurt.jar");
	// usw. kann auch dynamisch geladen werden

	Iterator i = jars.iterator();
	while (i.hasNext()) {
	    System.load((String) i.next());
	}
    }

    protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
	return super.loadClass(name, resolve);
    }
}


wäre das möglich - oder gibt es bessere Möglichkeiten?


Vielen Dank im Voraus für eure Hilfe.

Gruss Nik
 
Hallo,

schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * @author Thomas.Darimont
 */
public class DynamicClasspathExtensionExample {

  /**
   * @param args
   */
  public static void main(String[] args) {
    try {
      Class.forName("com.google.inject.Injector");
      System.out.println("Found");
    } catch (ClassNotFoundException e) {
     System.out.println(e.getMessage() + " not found...");
    }
    addJarsToClassPath(Thread.currentThread().getContextClassLoader(), new File[]{new File("D:/stuff/google/guice/1.0/guice-1.0.jar")});
    try {
      Class.forName("com.google.inject.Injector");
      System.out.println("Found");
    } catch (ClassNotFoundException e) {
      System.out.println(e.getMessage() + " not found...");
    }
  }


  private static void addJarsToClassPath(ClassLoader classLoader, File[] jars) {
    if (classLoader instanceof URLClassLoader) {
      try {
        Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
        addUrlMethod.setAccessible(true);
        if (null != addUrlMethod) {
          for (File jar : jars) {
            try {
              addUrlMethod.invoke(classLoader, jar.toURI().toURL());
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }

    }
  }
}

Ausgabe:
Code:
com.google.inject.Injector not found...
Found

Gruß Tom
 
Wow, schon mal vielen Dank!

Mist, ich hatte vergessen zu sagen, dass das mit Java 1.4 laufen sollte. (Sorry, kann ich leider nicht ändern)

Ich habe dann versucht dieses auf 1.4 anzupassen, sowie so zu erweitern, dass ich anstatt die jar-liste einen folder angeben kann. Bin aber daran gescheitert.

Mein angepasster Code sieht nun so aus:

Java:
public class MyDynamicClasspathExtension{

    public static void main(String[] args) {
	try {
	    Class.forName("com.sun.star.wizards.agenda.AgendaItem");
	    System.out.println("Found");
	} catch (ClassNotFoundException e) {
	    System.out.println(e.getMessage() + " not found...");
	}
	addJarsToClassPath(Thread.currentThread().getContextClassLoader(), new File("C:/Programme/OpenOffice.org 2.3/program/classes"));
	try {
	    Class.forName("com.sun.star.wizards.agenda.AgendaItem");
	    System.out.println("Found");
	} catch (ClassNotFoundException e) {
	    System.out.println(e.getMessage() + " not found...");
	}
    }

    private static void addJarsToClassPath(ClassLoader classLoader, File folder) {
	if (classLoader instanceof URLClassLoader) {
	    try {
		if (folder.exists()) {
		    File[] jarFiles = folder.listFiles(new FileFilter() {
			public boolean accept(File arg0) {
			    if (arg0.toString().lastIndexOf(".jar") != -1)
				return true;
			    else
				return false;
			}
		    });
		    Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
		    addUrlMethod.setAccessible(true);
		    File[] jars = new File[jarFiles.length];
		    if (null != addUrlMethod) {
			for (int i = 0; i < jarFiles.length; i++) {
			    System.out.println(jarFiles[i].toString());
			    jars[i] = new File(jarFiles[i].toString());
			}
			addUrlMethod.invoke((Object) classLoader, jars);
		    }
		}
	    } catch (Exception e) {
		e.printStackTrace();
	    }
	}
    }
}

was dann bei mir rauskommt ist das:
Code:
com.sun.star.wizards.agenda.AgendaItem not found...
C:\Programme\OpenOffice.org 2.3\program\classes\agenda.jar
C:\Programme\OpenOffice.org 2.3\program\classes\aportisdoc.jar
C:\Programme\OpenOffice.org 2.3\program\classes\bsh.jar
C:\Programme\OpenOffice.org 2.3\program\classes\classes.jar
C:\Programme\OpenOffice.org 2.3\program\classes\commonwizards.jar
C:\Programme\OpenOffice.org 2.3\program\classes\fax.jar
C:\Programme\OpenOffice.org 2.3\program\classes\form.jar
C:\Programme\OpenOffice.org 2.3\program\classes\hsqldb.jar
C:\Programme\OpenOffice.org 2.3\program\classes\java_uno.jar
C:\Programme\OpenOffice.org 2.3\program\classes\java_uno_accessbridge.jar
C:\Programme\OpenOffice.org 2.3\program\classes\js.jar
C:\Programme\OpenOffice.org 2.3\program\classes\juh.jar
C:\Programme\OpenOffice.org 2.3\program\classes\jurt.jar
C:\Programme\OpenOffice.org 2.3\program\classes\jut.jar
C:\Programme\OpenOffice.org 2.3\program\classes\letter.jar
C:\Programme\OpenOffice.org 2.3\program\classes\officebean.jar
C:\Programme\OpenOffice.org 2.3\program\classes\pexcel.jar
C:\Programme\OpenOffice.org 2.3\program\classes\pocketword.jar
C:\Programme\OpenOffice.org 2.3\program\classes\query.jar
C:\Programme\OpenOffice.org 2.3\program\classes\report.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ridl.jar
C:\Programme\OpenOffice.org 2.3\program\classes\sandbox.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ScriptFramework.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ScriptProviderForBeanShell.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ScriptProviderForJava.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ScriptProviderForJavaScript.jar
C:\Programme\OpenOffice.org 2.3\program\classes\sdbc_hsqldb.jar
C:\Programme\OpenOffice.org 2.3\program\classes\serializer.jar
C:\Programme\OpenOffice.org 2.3\program\classes\table.jar
C:\Programme\OpenOffice.org 2.3\program\classes\unoil.jar
C:\Programme\OpenOffice.org 2.3\program\classes\unoloader.jar
C:\Programme\OpenOffice.org 2.3\program\classes\web.jar
C:\Programme\OpenOffice.org 2.3\program\classes\writer2latex.jar
C:\Programme\OpenOffice.org 2.3\program\classes\xalan.jar
C:\Programme\OpenOffice.org 2.3\program\classes\xercesImpl.jar
C:\Programme\OpenOffice.org 2.3\program\classes\xmerge.jar
C:\Programme\OpenOffice.org 2.3\program\classes\XMergeBridge.jar
C:\Programme\OpenOffice.org 2.3\program\classes\xml-apis.jar
C:\Programme\OpenOffice.org 2.3\program\classes\XSLTFilter.jar
C:\Programme\OpenOffice.org 2.3\program\classes\XSLTValidate.jar
com.sun.star.wizards.agenda.AgendaItem not found...
java.lang.IllegalArgumentException: wrong number of arguments
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at MyDynamicClasspathExtension.addJarsToClassPath(MyDynamicClasspathExtension.java:45)
	at MyDynamicClasspathExtension.main(MyDynamicClasspathExtension.java:16)

Desweiteren habe ich mir dann auch überlegt, wie ich dies dann der jvm bekannt machen soll, dass sie dieses dann auch ausführt. Sorry, sind vielleicht banale Fragen, doch ich programmiere leider noch nicht so lange Java.

Vielen Dank für eure Antworten.


Gruss Nik
 
Zuletzt bearbeitet:
Habs hingekriegt auf 1.4.

Falls es jemanden interessiert hier noch der lauffähige code. Wenn man sich mal einwenig mit Reflection beschäftigen würde, kommt man sofort drauf... :)
Java:
public class MyDynamicClasspathExtension {

    public static void main(String[] args) {
	try {
	    Class.forName("com.sun.star.wizards.agenda.AgendaItem");
	    System.out.println("Found");
	} catch (ClassNotFoundException e) {
	    System.out.println(e.getMessage() + " not found...");
	}
	addJarsToClassPath(Thread.currentThread().getContextClassLoader(), new File("C:/Programme/OpenOffice.org 2.3/program/classes"));
	try {
	    Class.forName("com.sun.star.wizards.agenda.AgendaItem");
	    System.out.println("Found");
	} catch (ClassNotFoundException e) {
	    System.out.println(e.getMessage() + " not found...");
	}
    }

    private static void addJarsToClassPath(ClassLoader classLoader, File folder) {
	if (classLoader instanceof URLClassLoader) {
	    try {
		if (folder.exists()) {
		    File[] jarFiles = folder.listFiles(new FileFilter() {
			public boolean accept(File arg0) {
			    if (arg0.toString().lastIndexOf(".jar") != -1)
				return true;
			    else
				return false;
			}
		    });
		    Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
		    addUrlMethod.setAccessible(true);
		    if (null != addUrlMethod) {
			for (int i = 0; i < jarFiles.length; i++) {
			    System.out.println(jarFiles[i].toString());
			    addUrlMethod.invoke((Object) classLoader, new Object[] { jarFiles[i].toURI().toURL() });
			}

		    }
		}
	    } catch (Exception e) {
		e.printStackTrace();
	    }
	}
    }
}

und die Ausgabe dazu:
Code:
com.sun.star.wizards.agenda.AgendaItem not found...
C:\Programme\OpenOffice.org 2.3\program\classes\agenda.jar
C:\Programme\OpenOffice.org 2.3\program\classes\aportisdoc.jar
C:\Programme\OpenOffice.org 2.3\program\classes\bsh.jar
C:\Programme\OpenOffice.org 2.3\program\classes\classes.jar
C:\Programme\OpenOffice.org 2.3\program\classes\commonwizards.jar
C:\Programme\OpenOffice.org 2.3\program\classes\fax.jar
C:\Programme\OpenOffice.org 2.3\program\classes\form.jar
C:\Programme\OpenOffice.org 2.3\program\classes\hsqldb.jar
C:\Programme\OpenOffice.org 2.3\program\classes\java_uno.jar
C:\Programme\OpenOffice.org 2.3\program\classes\java_uno_accessbridge.jar
C:\Programme\OpenOffice.org 2.3\program\classes\js.jar
C:\Programme\OpenOffice.org 2.3\program\classes\juh.jar
C:\Programme\OpenOffice.org 2.3\program\classes\jurt.jar
C:\Programme\OpenOffice.org 2.3\program\classes\jut.jar
C:\Programme\OpenOffice.org 2.3\program\classes\letter.jar
C:\Programme\OpenOffice.org 2.3\program\classes\officebean.jar
C:\Programme\OpenOffice.org 2.3\program\classes\pexcel.jar
C:\Programme\OpenOffice.org 2.3\program\classes\pocketword.jar
C:\Programme\OpenOffice.org 2.3\program\classes\query.jar
C:\Programme\OpenOffice.org 2.3\program\classes\report.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ridl.jar
C:\Programme\OpenOffice.org 2.3\program\classes\sandbox.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ScriptFramework.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ScriptProviderForBeanShell.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ScriptProviderForJava.jar
C:\Programme\OpenOffice.org 2.3\program\classes\ScriptProviderForJavaScript.jar
C:\Programme\OpenOffice.org 2.3\program\classes\sdbc_hsqldb.jar
C:\Programme\OpenOffice.org 2.3\program\classes\serializer.jar
C:\Programme\OpenOffice.org 2.3\program\classes\table.jar
C:\Programme\OpenOffice.org 2.3\program\classes\unoil.jar
C:\Programme\OpenOffice.org 2.3\program\classes\unoloader.jar
C:\Programme\OpenOffice.org 2.3\program\classes\web.jar
C:\Programme\OpenOffice.org 2.3\program\classes\writer2latex.jar
C:\Programme\OpenOffice.org 2.3\program\classes\xalan.jar
C:\Programme\OpenOffice.org 2.3\program\classes\xercesImpl.jar
C:\Programme\OpenOffice.org 2.3\program\classes\xmerge.jar
C:\Programme\OpenOffice.org 2.3\program\classes\XMergeBridge.jar
C:\Programme\OpenOffice.org 2.3\program\classes\xml-apis.jar
C:\Programme\OpenOffice.org 2.3\program\classes\XSLTFilter.jar
C:\Programme\OpenOffice.org 2.3\program\classes\XSLTValidate.jar
Found


Nun aber noch die Frage, wie übergebe ich das der JVM, dass sie dasautomatisch ausführt? Soll ich dies als ausfürhbares JAR in den Classpath stellen oder was gibts sonst für Möglichkeiten?

Vielen Dank im Voraus

Gruss Nik
 
Zurück