# ClassNotFoundException in JAR File



## Gast (15. Apr 2005)

Hallo,

ich habe es nun geschafft, alle notwendigen Bibibliothken in das ausführbare Jar file einzubinden, schon kommt das nächste Problem:

In meinem Programm kann der Anwender eine eigen Java-Datei erstellen, die dann mittels meiner Anwendung ausgeführt werden kann. Beim Ausführen unter Eclipse funktioniert alles wunderbar, aber in dem Jar-File bringt er den Fehler, dass er die temporär erstellte Klasse nicht findet. Wie kann er sie unter Eclipse finden aber im Jar File nicht? Er hat diese Dateien übrigens korrekt erstellt, also sie sind im aktuellen Verzeichnis der Jar-Datei vorhanden. Woher kann dann der Fehler kommen? Im folgenden findet ihr meinen Code:

CompileKlasse

```
public class CompileThread extends Thread
{
	File file;
	String classname,filename;
	
	public CompileThread(File file2,String classname2,String filename2)
	{
		file=file2;
		filename=filename2;
		classname=classname2;

	}
	
	public void run()
	{
		if(this.isInterrupted()==false)
		{
	
	//Main Methode compilieren
	String[] args =new String[]{"-d",System.getProperty("user.dir"),filename};
	int status =Main.compile(args);
			
	switch(status)
	{
		case 0: 
			//Temporaere Datei wieder loeschen 
			new File(file.getParent(),classname + ".class").deleteOnExit();
			try
			{
				Class clazz=Class.forName(classname);
				Method main =clazz.getMethod("main",new Class[]{String[].class});
				main.invoke(null,new Object[]{new String[0]});	
			}catch(InvocationTargetException ex)
			{
				System.out.println("Fehler beim Ausfuehren!");
				System.out.println("Exception in main "+ ex.getTargetException());
				ex.getTargetException().printStackTrace();
				
			}catch(Exception ex)
			{
				System.out.println("Fehler beim Ausfuehren!");
				System.out.println(ex.toString());
				
			}
			break;
		case 1: System.out.println("Compile status: ERROR");break;
		case 2: System.out.println("Compile status: CMDERR");break;
		case 3: System.out.println("Compile status: SYSERR");break;
		case 4: System.out.println("Compile status: ABNORMAL");break;
		default: System.out.println("Compile status: Unknown exit status");
		}

		}
		
	
		
	}
		

}
```

Ausführklasse:

```
//fuehrt den Algorithmus aus
	//erstellt dafuer Temporaere Java-Datei
	//schreibt Variablen und Alg-Eingaben in Datei
	//compiliert die temporaere Datei und fuehrt sie aus	
	synchronized public void ausfuehren(boolean schrittweise)
	{
		//Algorithmus prüfen
		this.pruefeVariablenReihe();
		this.pruefeVariablenWerte();
		
		//bevor eigentliches Ausfuehren stattfindet, wird geprueft, ob Variablen Korrekt sind und 
		//Algorithmus ausgefuellt wurde, sonst erscheint Fehlermessage
		if(this.sindVariablenKorrekt()==true && this.pruefeAusgefuellt()==true)
		{
			try
			{
				//temporaere Java-Datei erstellen
				File file=File.createTempFile("Jav",".java",new File(System.getProperty("user.dir")));
				file.deleteOnExit();
				String filename=file.getName();
				String classname=filename.substring(0,filename.length()-5);
				ausgabeDatei = new PrintWriter (new FileOutputStream(file));
				//Klassenname in Datei schreiben
				ausgabeDatei.println(getSpeicherText(1,classname,schrittweise));
				//definierte Variablen ermitteln (String mit Typ,Name,Wert)
		  	
				if(this.varDef==false)
				setDefinierteVariablen();
				//Liste dieser Strings mit Variablen Typ,Name,Wert durchlaufen
				Iterator i=variablenListe.iterator();
				while(i.hasNext())
				{
					//VariablenStrings in Datei schreiben
					Variable var=(Variable)i.next();
					String str1=var.getTyp();
					String str2=var.getName();
					String str3=var.getWert();
					String result=str1+" "+str2+"="+str3+"; \r\n";
					ausgabeDatei.println(result);
				}
			
			
				ausgabeDatei.println("\r\n");			
				//Text aus AlgFenster in Datei schreiben
				ausgabeDatei.println(this.getText() );
				//Alle Variablen durchlaufen
			

				//StandardVariablen Ausgabe in Datei schreiben
				ausgabeDatei.println(getSpeicherText(2,classname,schrittweise));
			
				ausgabeDatei.flush();
				ausgabeDatei.close();
			
				Thread compile=new CompileThread(file,classname,filename);
				compile.start();
				try
				{
					compile.join(this.getWaitSec());
				
					if(compile.isAlive()==true)
					{
						compile.interrupt();
						System.out.println("Ausfuehren wurde nach "+(this.getWaitSec()/1000)+" beendet!");
						JOptionPane.showMessageDialog(StructX.getAktivFenster().getHaupFenster(),"Programm wird beendet!!","Endlosschleife",JOptionPane.ERROR_MESSAGE);
						System.exit(0);
					}
					
				
				}catch(InterruptedException ie){	}
				
			
			}
			catch (IOException e) { System.out.println("Fehler!");}
		}
		//Algorithmus noch nicht fertig zum Ausfuehren
		else
		{
			JOptionPane.showMessageDialog(StructX.getAktivFenster(),"Bitte Algorithmus pruefen","Fehler",JOptionPane.INFORMATION_MESSAGE);
		}
```

Kann mir jemand helfen.


----------



## semi (15. Apr 2005)

Mit
	
	
	
	





```
...
Class clazz=Class.forName(classname);
...
```
klappt es nicht.
Versuche das hier
	
	
	
	





```
URLClassLoader l = new URLClassLoader(new URL[] { new URL("file://localhost/" + file.getParent().getAbsolutePath()) });
Class c = l.loadClass(classname);
Method m = c.getMethod("main", new Class[] { String[].class });
m.invoke(null, new Object[] {new String[0]});
```


----------



## Guest (15. Apr 2005)

bei 


```
file.getParent().getAbsolutePath()
```

kommt folgende Fehlermeldung:
Methode getAbsolutePath() is undefined for the typ String.


----------



## Guest (15. Apr 2005)

Das Problem mit dem String ist gelöst.  Der richtige Aufruf war file.getParent*File*.getAbsolutePath().
Aber beim Ausführen nach dem Erstellen der Jar Datei kommt noch immer eine ClassNotFound Exception. Ist die URL falsch? Was muss ich einsetzen, damit eine Datei im gleichen Folder wie die Jar Datei gefunden werden kann?


----------



## semi (16. Apr 2005)

In Deinem Code sehe ich nichts mit Jar-Dateien.
In dem Clasloader-Beispiel gehe ich davon aus, dass die compilierte Datei
in einem Verzeichnis liegt (undauch keine package-Aweisung im Sourcecode)
Die Jar-URL sollte wie folgt aussehen

jar:file:/wo/auch/immer/archive.jar!/

Danach kannst Du die Klassen laden.


----------



## Guest (16. Apr 2005)

Die Datei liegt in keinem Jar File.
In der Klasse Algorithmus wird zuerst eine Java Datei erstellt (im gleichen Verzeichnis wie das selbstausführbare JarFile meiner Anwendung). Danach wird die Class-Datei mit dem gleichen Namen erstellt, auch im selben Verzeichnis mit der Java und der Jar Datei. Beim Ausführen unter Eclipse funktioniert alles wunderbar, nur beim Ausführen über das selbstausführbare JarFile kann er die Class-Datei nicht finden. Wieso ist da so ein Unterschied?


----------



## Guest (16. Apr 2005)

Ich hab den Quellcode noch mal geringfügig geändert, um mir zuerst den Pfad der Klassendatei beim Erstellen und dann in der URL auszugeben. Die Pfad an sich ist der gleiche, aber in der URL steht halt noch "file:/" davor und der Slash ist umgedreht. Der Pfad der angelegten ClassDatei geht also etwa so C:\...\...\Klasse.class. Die URL sieht so aus: file:/C:/.../.../Klasse.class

Der Code:

```
//Main Methode compilieren
	String[] args =new String[]{"-d",System.getProperty("user.dir"),filename};
	int status =Main.compile(args);
			
	switch(status)
	{
		case 0: 
			//Temporaere Datei wieder loeschen 
			File classFile=new File(file.getParentFile().getAbsolutePath(),classname + ".class");
			System.out.println("ClassFile pfad: "+classFile.getAbsolutePath());
			
			classFile.deleteOnExit();
			
			try
			{
				//Class clazz=Class.forName(classname);
				URL url=new File(classFile.getAbsolutePath()).toURL();
				
				URLClassLoader l = new URLClassLoader(new URL[] { url }); 
				
				System.out.println("URL pfad: "+url);
			
				Class clazz = l.loadClass(classname); 
				
				Method m = clazz.getMethod("main", new Class[] { String[].class }); 
				m.invoke(null, new Object[] {new String[0]});
					
			}catch(InvocationTargetException ex)
			{
				System.out.println("Fehler beim Ausfuehren!");
				System.out.println("Exception in main "+ ex.getTargetException());
				ex.getTargetException().printStackTrace();
				
			}catch(Exception ex)
			{
				System.out.println("Fehler beim Ausfuehren!");
				System.out.println(ex.toString());
				
			}
			break;
		case 1: System.out.println("Compile status: ERROR");break;
		case 2: System.out.println("Compile status: CMDERR");break;
		case 3: System.out.println("Compile status: SYSERR");break;
		case 4: System.out.println("Compile status: ABNORMAL");break;
		default: System.out.println("Compile status: Unknown exit status");
		}
```


Kann es darin liegen? Oder mache ich noch was anderes falsch? Die Frage ist halt immer noch: Wieso macht er dass denn unter Eclipse, aber nicht in meinem JarFile?


----------



## semi (16. Apr 2005)

Also bei mir geht's. Hilft nicht weiter, was? :bae: 

Kann es sein, dass sich die neu compilierte Klasse auf etwas bezieht,
was in dem Jar-Archiv vorhanden ist?

Versuche vielleicht noch den anderen Konstruktor.
new URLClassLoader(..wie gehabt.., this.getClass().getClassLoader());

Ansonsten habe ich keine Ahnung, was das Problem sein könnte.


----------



## semi (16. Apr 2005)

Aghhh! :autsch: 
Was ist das in Deinem Code?

```
...
URL url=new File(classFile.getAbsolutePath()).toURL(); 
URLClassLoader l = new URLClassLoader(new URL[] { url }); 
...
```
Mach' mal
	
	
	
	





```
...
URL url=classFile.getParentFile().toURL();
URLClassLoader l = new URLClassLoader(new URL[] { url }); 
...
```
daraus.


----------



## Guest (16. Apr 2005)

Ups,

da hab ich wohl beim vielen hin und her probieren mal schnell den Pfad verwechselt. Es geht jetzt!!
DANKE!!!!!!!!!   :applaus: 

Die Frage ist natürlich immer noch, wieso das Ausführen unter Eclipse funktioniert hat? Wie hat er die Klasse da gefunden??  ???:L


----------



## semi (16. Apr 2005)

Anonymous hat gesagt.:
			
		

> Die Frage ist natürlich immer noch, wieso das Ausführen unter Eclipse funktioniert hat? Wie hat er die Klasse da gefunden??  ???:L


Auch beim allerersten Aufruf?
Kann es sein, dass die compilierte Klasse bereits existriert hat, als es funktionierte?
Lösche mal die compilierte Klasse und starte es mal just for fun erneut.


----------

