Mam projekt Eclipse, który eksportuję do słoika, który można uruchomić, używając kompilacji Ant i używam programu ładującego jar-in-jar, aby umieścić kilka bibliotek jar w słoiku projektu. Kiedyś to działało i jak pamiętam, aktualizacja do Java 9 jest tym, co ją zepsuło. Mogłem się mylić, ale po prostu używałem mojego słoika przez jakiś czas, aż przestał działać.

Uruchomienie projektu w Eclipse działa dobrze, ale kiedy używam jar i wywołuję metodę z jednej z bibliotek, otrzymuję NoClassDefFoundError. Nie ma znaczenia, która biblioteka.

java.lang.NoClassDefFoundError: myutils/MyUtils
        at packagename.Utils.input(Utils.java:42)
        at packagename.Main.main(Main.java:83)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.ClassNotFoundException: myutils.MyUtils
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:436)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        ... 7 more

Oto kompilacja Ant:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="create_run_jar" name="Create Runnable Jar for Project ProjectName with Jar-in-Jar Loader">
    <!--this file was created by Eclipse Runnable JAR file Export Wizard-->
    <!--ANT 1.7 is required-->
    <!--define folder properties-->
    <property name="dir.buildfile" value="."/>
    <property name="dir.workspace" value="${dir.buildfile}/.."/>
    <property name="dir.libraries" value="${dir.buildfile}/../../libraries"/>
    <property name="dir.projectjars" value="${dir.buildfile}/../../project-jars"/>
    <target name="create_run_jar">
        <jar destfile="${dir.projectjars}/jarname.jar">
            <manifest>
                <attribute name="Main-Class" value="org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader"/>
                <attribute name="Rsrc-Main-Class" value="packagename.Main"/>
                <attribute name="Class-Path" value="."/>
                <attribute name="Rsrc-Class-Path" value="./ guava-19.0.jar jsoup-1.9.1.jar myutils.jar"/>
            </manifest>
            <zipfileset src="jar-in-jar-loader.zip"/>
            <fileset dir="${dir.buildfile}/bin"/>
            <zipfileset dir="${dir.libraries}" includes="guava-19.0.jar"/>
            <zipfileset dir="${dir.libraries}" includes="jsoup-1.9.1.jar"/>
            <zipfileset dir="${dir.projectjars}" includes="myutils.jar"/>
        </jar>
    </target>
</project>

EDYCJA: Oto MANIFEST.MF:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.10.5
Created-By: 12.0.2+10 (Oracle Corporation)
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
Rsrc-Main-Class: packagename.Main
Rsrc-Class-Path: ./ guava-19.0.jar jsoup-1.9.1.jar myutils.jar
Class-Path: .
1
Blrp 20 grudzień 2019, 03:39
Możesz to dokładniej zbadać, otwierając wygenerowany plik jar, używając na przykład WinRar (lub dowolnego innego programu zip, który obsługuje pliki .jar) i sprawdzając, czy biblioteki faktycznie trafiają do tego jara, czy nie. Znalezienie słoików zredukowałoby problem do problemu z ładowaniem klas, nie znalezienie słoików zredukowałoby problem do problemu z kompilacją mrówek (cieniowanie zależności w zbudowanym słoiku).
 – 
Pieter12345
20 grudzień 2019, 05:19
Słoiki rzeczywiście tam są.
 – 
Blrp
20 grudzień 2019, 13:10
1
W takim przypadku ładowarka-w-słoiku nie ładuje prawidłowo słoików. Główna klasa, którą wywołujesz, uruchamia ten kod, aby uzyskać odniesienia do słoików: github.com/eclipse/eclipse.jdt.ui/blob/master/… Widać, że pobiera nazwy słoików z manifestu. Być może musisz uwzględnić te nazwy słoików w manifeście? Aby uzyskać dokładny format, musiałbyś zapoznać się z dokumentacją programu ładującego jar-in-jar.
 – 
Pieter12345
21 grudzień 2019, 01:55
Cóż, dodałem manifest do OP. Nawet gdybym wiedział, jak zmienić manifest, aby działał, nie wiem, jak zmieniłbym kompilację Ant, aby utworzyć odpowiedni manifest.
 – 
Blrp
22 grudzień 2019, 03:57
Wpadłem na ten problem dzisiaj, gdy próbowałem użyć starego build.xml z projektu, który zrobiłem kilka lat temu (Java 8). To po prostu nie działało (ale kiedyś działało dobrze). Skończyło się na naprawieniu tego przez ponowne wygenerowanie pliku build.xml z poziomu Eclipse (poprzez zaznaczenie pola wyboru "Zapisz jako skrypt ANT" w kreatorze "Eksportuj runnable jar"). Możesz porównać stare i nowe, aby zobaczyć różnice (co musi być ważne, ponieważ nowy działał dobrze). Może to zadziała dla ciebie.
 – 
Kevin
8 luty 2020, 02:02

1 odpowiedź

Problem

Prawdopodobnie twój plik jar-in-jar-loader.zip jest nieaktualny i nieodpowiedni dla Javy >= 9, miałem ten sam problem.

Rozwiązanie

Aby pobrać najnowszą wersję tego pliku, kliknij prawym przyciskiem myszy swój projekt -> Eksportuj -> Uruchomiony plik JAR -> Zaznacz "Zapisz jako skrypt ANT" -> Zakończ. Spowoduje to utworzenie najnowszej wersji jar-in-jar-loader.zip w katalogu projektu. Sam skrypt mrówkowy nie musi być dostosowywany, przynajmniej w moim przypadku.

0
user7291698 10 sierpień 2021, 14:41