IllegalStateExceptions in Spring Boot JAR-Datei

obito64

Mitglied
Java:
Exception in thread "main" java.lang.IllegalStateException: Failed to get nested archive for entry BOOT-INF/lib/annotation-4.0.0.jar

Ich habe mein Program über maven mit YGuard obfuscatet.

Code:
<

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>package.App</mainClass>
                </configuration>

            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>
            <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.8</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <id>obfuscate</id>
                        <configuration>
                            <tasks>
                                <property name="runtime_classpath"
                                    refid="maven.runtime.classpath" />
                                <taskdef name="yguard"
                                    classname="com.yworks.yguard.YGuardTask"
                                    classpath="${runtime_classpath}" />
                                <yguard>

                                    <inoutpair
                                        in="${project.build.directory}/${project.build.finalName}.jar"
                                        out="${project.build.directory}/${project.build.finalName}_obfuscated.jar" />
                                    <attribute name="Deprecated" />


                                    <rename mainclass="package.App"
                                        logfile="${project.build.directory}/yguard.log.xml">
                                        <keep>
                                            <method class="package.App"
                                                name="void main(java.lang.String[])" />
                                            <class classes="protected"
                                                methods="protected"
                                                fields="protected" />
                                        </keep>
                                    </rename>
                                </yguard>
                            </tasks>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>

Und wenn ich meine Obfuscated.jar ausführen möchte bekomme ich diese Fehlermledung:

Code:
Exception in thread "main" java.lang.IllegalStateException: Failed to get nested archive for entry BOOT-INF/lib/annotation-4.0.0.jar
        at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(Unknown Source)
        at org.springframework.boot.loader.archive.JarFileArchive$_B.B(Unknown Source)
        at org.springframework.boot.loader.archive.JarFileArchive$_B.A(Unknown Source)
        at org.springframework.boot.loader.archive.JarFileArchive$_D.next(Unknown Source)
        at org.springframework.boot.loader.PropertiesLauncher$_A.B(Unknown Source)
        at org.springframework.boot.loader.PropertiesLauncher$_A.<init>(Unknown Source)
        at org.springframework.boot.loader.PropertiesLauncher.getClassPathArchivesIterator(Unknown Source)
        at org.springframework.boot.loader.Launcher.launch(Unknown Source)
        at org.springframework.boot.loader.PropertiesLauncher.main(Unknown Source)
Caused by: java.io.IOException: Unable to open nested jar file 'BOOT-INF/lib/annotation-4.0.0.jar'
        at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(Unknown Source)
        at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(Unknown Source)
        ... 9 more
Caused by: java.lang.IllegalStateException: Unable to open nested entry 'BOOT-INF/lib/annotation-4.0.0.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file

Leider konnte ich im internet nichts hilfreiches finden.
 

KonradN

Super-Moderator
Mitarbeiter
Ich hatte so ein Problem bisher nicht. Ich habe jetzt auch einmal recherchiert und das Problem scheint darauf zurück geführt zu werden, dass da in einem runnable jar eine komprimierte jar Datei ist. Aber das jar mit den Abhängigkeiten in BOOT-INF/lib/ wird doch vom Spring Plugin erstellt, oder?

Die erste Fragestellung wäre daher für mich:
Ist das Problem yguard bezogen? Sprich: kannst Du das ursprüngliche jar File ausführen? Wenn ich deinen anderen Thread richtig verstanden habe, dann hast Du ja am Ende ein jar File und das wird dann von yguard verarbeitet und Du bekommst ein neues jar. Tritt das Problem mit beiden jar Dateien auf?
 

obito64

Mitglied
Ich hab es mal ausprobiert. Mit der normalen jar klappt alles. Also mit der Tool.jar klappt es aber mit der Tool-Obfuscatet.jar klappt es nicht
 

KonradN

Super-Moderator
Mitarbeiter
Ok, dann wäre einmal interessant zu wissen, wo die Unterschiede sind (Ausser den Änderungen am Code selbst). Da die Fehlermeldung darauf hindeutet, dass es an dem Komprimieren liegt, könnte man das Vergleichen. Leider habe ich so auf Anhieb keinen einfachen Check gesehen, wie man schauen kann, ob eine jar Datei komprimiert wurde oder nicht. Daher habe ich da mal einfach ein kleines bisschen Code für:

Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class JarCompressionChecker {

    public static boolean isJarCompressed(File file) {
        try (JarFile jarFile = new JarFile(file)) {
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                if (entry.getMethod() != JarEntry.STORED) {
                    // Wenn ein Eintrag nicht mit der Methode STORED markiert ist, dann ist die JAR-Datei komprimiert
                    return true;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false; // Alle Einträge sind mit STORED markiert, also nicht komprimiert
    }

    public static void main(String[] args) {
        File file = new File(args[0]);
        if (isJarCompressed(file)) {
            System.out.println("Die JAR-Datei ist komprimiert.");
        } else {
            System.out.println("Die JAR-Datei ist nicht komprimiert.");
        }
    }
}
(Mit freundlicher Unterstützung von ChatGPT.)

Mit aktueller Java Version kannst Du das ohne es vorher zu übersetzen direkt nutzen z.B. per
java JarCompressionChecker.java Tool.jar

Da wäre dann jetzt interessant, was da die Unterschiede sind:
a) von den jar Dateien selbst, also Tool.jar und Tool-Obfuscated.jar
b) Wenn Du die jar Dateien entpackst, die jeweilige Datei BOOT-INF/lib/annotation-4.0.0.jar

Entpacken kannst Du z.B. per jar xvf datei .

Da ich hier aber - wie du evtl. merkst - gerade selbst etwas im dunkeln tappe, ist es evtl. auch möglich, ein kleines Beispiel-Projekt zu erstellen? Also einfach ein spring boot Projekt erstellen mit den Abhängigkeiten, evtl. eine 08/15 Funktionalität (also z.B. bei Spring Web ein Controller der "Hello World" zurück gibt), und die Anpassungen an der pom.xml so dass das Problem nachgestellt ist. Das könnte interessant sein, denn dann könnte man selbst etwas herum spielen um den Fehler zu finden ...
 

obito64

Mitglied
Ich hab jetzt leider nicht ganz genau verstanden, wie ich vorgehen soll?
Wenn ich diese Klasse erstelle, hab ich doch theoretisch 2 Main Klassen, was eig nicht richtig ist.
Soll ich meine Main klasse jetzt löschen und in deine klasse rein implementieren?

Edit (Ich habe java JarCompressionChecker.java Tool.jar eingegeben und die Fehlermeldung bekommen:
Java:
Fehler: Hauptklasse JarCompressionChecker.java konnte nicht gefunden oder geladen werden
Ursache: java.lang.ClassNotFoundException: JarCompressionChecker.java

)

Zu diesem Zeitpunkt hab ich noch 2 Main klassen
 

KonradN

Super-Moderator
Mitarbeiter
Die Klasse kannst Du als ein Tool ansehen. Die gehört nicht in Dein Projekt. Du kannst diese also einfach in das target Verzeichnis kopieren.
Und dann nutzt Du dieses Tool, um Dir anzeigen zu lassen, ob eine jar Datei auch compression nutzt oder nicht.

Aufrufen kannst Du das Tool einfach mit
java JarCompressionChecker.java zuCheckendeJarDatei
Dabei kannst Du sowohl bei JarCompressionChecker.java also auch bei der "zuChechendeJarDatei" einen Pfad mit angeben, also z.B. etwas wie:
java ../JarCompressionChecker.java tmp/BOOT-INF/lib/annotation-4.0.0.jar
 

obito64

Mitglied
Ich verstehe nicht ganz genau wie ich das Tool (Klasse) in mein traget kriegen soll. Ich kann in meinem Target keine Klassen erstellen :/
 

KonradN

Super-Moderator
Mitarbeiter
Du kannst einfach eine Datei erstellen. Wenn das die IDE nicht zulässt, dann nutz einen normalen Editor des Betriebssystems. Oder leg es an irgend einem anderen Ort an. Der target Ordner war nur ein Vorschlag.
 

obito64

Mitglied
Ich habe die Tool.jar und die Tool_Obfusctatet getstet beide sind Komprimiert. als ich diesen befehl eingegeben habe"
java java.java tmp/BOOT-INF/lib/annotation-4.0.0.jar"
Kam diese Fehlermeldung

Java:
java java.java tmp/BOOT-INF/lib/annotation-4.0.0.jar
java.nio.file.NoSuchFileException: tmp\BOOT-INF\lib\annotation-4.0.0.jar
        at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:85)
        at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
        at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108)
        at java.base/sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(WindowsFileAttributeViews.java:53)
        at java.base/sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(WindowsFileAttributeViews.java:38)
        at java.base/sun.nio.fs.WindowsFileSystemProvider.readAttributes(WindowsFileSystemProvider.java:199)
        at java.base/java.nio.file.Files.readAttributes(Files.java:1851)
        at java.base/java.util.zip.ZipFile$Source.get(ZipFile.java:1429)
        at java.base/java.util.zip.ZipFile$CleanableResource.<init>(ZipFile.java:718)
        at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:252)
        at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:181)
        at java.base/java.util.jar.JarFile.<init>(JarFile.java:346)
        at java.base/java.util.jar.JarFile.<init>(JarFile.java:317)
        at java.base/java.util.jar.JarFile.<init>(JarFile.java:283)
        at JarCompressionChecker.isJarCompressed(java.java:11)
        at JarCompressionChecker.main(java.java:28)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:419)
        at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
        at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
[B]Die JAR-Datei ist nicht komprimier[/B]t.
 

KonradN

Super-Moderator
Mitarbeiter
Das wäre ein Aufruf, wenn Du eine der erzeugten jar Dateien in einem Unterverzeichnis tmp entpackt hättest so dass Du
  • von dem aktuellen Verzeichnis aus die Datei tmp/BOOT-INF/lib/annotation-4.0.0.jar
  • im Verzeichnis die Datei java.java
hättest.

Im Augenblick ist das gerade recht deprimierend - wir stolpern hier massiv über triviale Grundlagen und ich kann dich hier nicht durch jeden noch so kleinen Schritt führen.

Evtl. gibst Du einfach mal das Projekt als ganzes weiter und dann kann man nachvollziehen, was da abgeht und so. Aber evtl. willst Du auch einfach auf die Nutzung von einem Obfuscator verzichten?
 

KonradN

Super-Moderator
Mitarbeiter
Ok, interessantes Problem.

Spring Boot erstellt ein jar File, bei dem dann die classes in BOOT-INF/classes/ liegen. Das ist so aber nicht vorgehen bei jar Files und daher wird das nicht von yguard unterstützt.

Diskussion dazu und weiterführende Links:
Yguard Obfuscation in a Spring Boot Project · Issue #43 · yWorks/yGuard (github.com)

Die Lösung ist dann hier zu finden:
yGuard/examples/processing/pom.xml at master · yWorks/yGuard (github.com)

Das habe ich einmal in dein pom.xml übernommen und es funktioniert. die pom.xml sende ich Dir per Email zu.
 

Neue Themen


Oben