Aplikacja jako .class działa a jako .jar - nie

0

Mam aplikację (specjalnie uproszczoną dla testowania)
import java.io.;
import jartest.
;
class JarTest {
static ProcTest pt;
public static void main(String[] args) {
File f;
f = new File(".");
String gdzie = f.getAbsolutePath();
System.out.println("JarTest: jestem tu: "+gdzie);
pt = new ProcTest();
}
}

Klasa ProcTest jest umieszczona w pliku JarTlib.jar , który znajduje się w katalogu C:\prolog, a ten katalog jest w zmiennej CLASSPATH
Jej kod źródłowy jest taki:

package jartest;
import java.io.;
import javax.swing.
;
public class ProcTest {
public ProcTest( ) {
Class c = getClass();
String klasa = c.getName();
System.out.println("ProcTest czyli: "+klasa);
}
}
Program JarTest skompilował się pomyślnie, a jego "zwykłe" uruchomienie djje oczekiwany wynik:
C:\prolog\JarTestKat>java JarTest
JarTest: jestem tu: C:\prolog\JarTestKat.
ProcTest czyli: jartest.ProcTest

Ale ten program umieściłem w pliku JarTest.jar a próba jego wykonania daje efekt taki:

C:\prolog\JarTestKat>java -jar JarTest.jar
JarTest: jestem tu: C:\prolog\JarTestKat.
Exception in thread "main" java.lang.NoClassDefFoundError: jartest/ProcTest
at JarTest.main(JarTest.java:13)
Caused by: java.lang.ClassNotFoundException: jartest.ProcTest
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 sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more

C:\prolog\JarTestKat>

Czy ktoś mógłby wytłumaczyć dlaczego tak się dzieje ?
Nie jest to w moim życiu zawodowym pierwszy przypadek, kiedy umieszczałem aplikację w pliku jar, ale dotychczas takich "efektów" nie miałem. Pierwszy raz natomiast zdarzyło się, że odwoływałem się do włosnych klas umieszczonych w innym katalogu i to nie będącym podkatalogiem katalogu aplikacji.
Będę wdzięczny za wszelkie wtjaśnienia

0

U mnie podobne podejście niby działa, z tym że swoje jarki mam w relatywnej ścieżce.
Sprawdź czy dobry classpath Ci sie generuje w pliku manifest.mf w jarku. Możliwe, że tam jest zły lub wcale go nie ma. Pomóc też mogłoby wywołanie z parametrem:

C:\prolog\JarTestKat>java -jar JarTest.jar -classpath c:\prolog\JarTlib.jar

edit:

Ładne rozwiązanie nie wymagające classpath;]

File file  = new File("c:\\myjar.jar");
 URL url = file.toURL();  
 URL[] urls = new URL[]{url};
 ClassLoader cl = new URLClassLoader(urls);

 Class cls = cl.loadClass("com.mypackage.myclass");

0

java -jar nie bierze pod uwagę '-cp'.
Do Class-Path manifestu tego jara dodaj ścieżkę, w której masz pakiet jartest. Jeśli folder jest w tym samym miejscu co jar, to tylko:
Class-Path: .

0

Dziękuję za wszystkie odpowiedzi. Postaram się je wypróbować. Z parametrem Class-Path w manifeście miałem ten kłopot, że kiedy go używałem, to "gubił się" parametr Main-Class, to znaczy w manifeście go nie było, chociaż w zewnętrznym pliku manifestu był.
na razie znalałem rozwiązanie: polega ono na tym, żeby w pliku jar umieścić wszystkie zewnętrzne klasy wraz z ich strukturą wynikającą z pakietów. Dość zgrabnie można to zrobić programem ant. Dla przedstawionego tu przykładziku skrypt build.xml wyglądał tak:

<?xml version="1.0" encoding="windows-1250"?> <project name="Test tworzenia JAR" default="build" basedir="."> <property name="srcdir" value="." /> <property name="srcdirextra" value="C:/prolog" /> <property name="destdir" value="build" /> <property name="docdir" value="doc" /> <property file="${user.home}/.ant.properties" /> <target name="compile" description="Kompiluje pliki źródłowe tego folderu i biblioteki"> <mkdir dir="${destdir}" /> <javac srcdir="${srcdir}" destdir="${destdir}" debug="on"> <include name="**/*.java" /> </javac> <javac srcdir="${srcdirextra}" destdir="${destdir}" debug="on"> <include name="jartest/**/*.java" /> </javac> </target> <target name="clean" description="Usuwa wszystkie pliki klas tego rozdziału"> <delete dir="${destdir}" failonerror="false" /> </target> <target name="build" depends="clean, compile" description="Kompiluje pliki źródłowe i tworzy archiwum JAR"> <jar jarfile="${basedir}/JarTest.jar"> <manifest> <attribute name="Main-Class" value="JarTest" /> </manifest> <fileset dir="${destdir}" includes="**/*.class" />
    </jar>
</target>
</project>

Ten skrypt jest zmodyfikowaną postacią skryptów z przykładów do książki
David Brackeen, Bret Baker, Laurence Vanhelsuwe "Java Tworzenie gier" wydawnictwo Helion.

To rozwiązanie jest może prostackie, ale działa i jest chyba najbardziej przenośne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1