Error creating shaded jar: Invalid signature file digest for Manifest main attributes

Updated:

Error creating shaded jar: Invalid signature file digest for Manifest main attributes 해결

Firebase API 를 6.3.1 에서 9.3.0 로 변경한 이후, maven build 실행시 다음과 같은 오류가 발생하였다.

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:2.4.3:shade (default) on project (프로젝트 이름): Error creating shaded jar: Invalid signature file digest for Manifest main attributes -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:


일반적인 원인은 maven-shade-plugin 으로 over-jar를 생성하는 과정에서 .RSA, .SF, .DSA 이 3가지 확장자 파일들이 병합이 안되는데 있었다.

Firebase API  버전업이 되면서, 특정 Jar의 서명파일에 문제가 있었던 것으로 추측이 된다.

따라서, pom.xml 의 maven-shade-plugin 에 Jar의 서명파일을 제외하도록 설정 코드를 추가하였다.

<configuration>
    <filters>
        <filter>
            <artifact>*:*</artifact>
            <excludes>
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>
            </excludes>
        </filter>
    </filters>
</configuration>

이는 JAR 병합 과정에서 기존 서명 파일을 완전히 무시하여 JAR 파일의 무결성 검증을 수행하지 않도록 한다.

이후 로컬에서 maven build를 실행하여도 동일한 오류가 발생하였다.

mvn clean install

→ 다만 위 방법으로 해결이 되지 않음.

이유는 maven-dependency-plugin 에 있었다.

Maven Dependency Plugin은 의존성 관리와 관련된 작업을 수행하며

maven-shade-plugin은 Fat JAR(Uber JAR)을 생성하면서 의존성을 병합한다.

  1. Maven Dependency Plugin: 의존성을 추출하거나 수정.
  2. Maven Shade Plugin: Fat JAR 생성.

따라서, maven-shade-plugin 에만 서명파일 제외 코드만 추가하면,

Maven Dependency Plugin의 의존성 JAR 파일을 복사하거나 추출하는 과정에서 서명 파일이 포함되어,

이후 shade plugin으로 fat jar 생성시 서명파일 오류가 발생하는 것이다.

→ 따라서 두 개의 plugin 모두 서명파일 제거가 필요하다.

<plugins>
    <plugin>
       <artifactId>maven-compiler-plugin</artifactId>
       <version>3.6.1</version>
       <configuration>
          <source>1.8</source>
          <target>1.8</target>
       </configuration>
    </plugin>

    <plugin>
       <artifactId>maven-dependency-plugin</artifactId>
       <executions>
          <execution>
             <id>unpack-dependencies</id>
             <phase>prepare-package</phase>
             <goals>
                <goal>unpack-dependencies</goal>
             </goals>
             <configuration>
                <outputDirectory>${project.build.directory}/classes</outputDirectory>
                <excludes>META-INF/*.SF</excludes>
                <excludes>META-INF/*.DSA</excludes>
                <excludes>META-INF/*.RSA</excludes>
             </configuration>
          </execution>
       </executions>
    </plugin>
    <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-shade-plugin</artifactId>
       <version>2.4.3</version>
       <executions>
          <execution>
             <phase>package</phase>
             <goals>
                <goal>shade</goal>
             </goals>
             <configuration>
                <filters>
                   <filter>
                      <artifact>*:*</artifact>
                      <excludes>
                         <exclude>META-INF/*.SF</exclude>
                         <exclude>META-INF/*.DSA</exclude>
                         <exclude>META-INF/*.RSA</exclude>
                      </excludes>
                   </filter>
                </filters>
                <transformers>
                   <transformer
                      implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                      <mainClass>(Main 클래스 경로)</mainClass>
                   </transformer>
                </transformers>
             </configuration>
          </execution>
       </executions>
    </plugin>
</plugins>

그 외

이번 에러를 해결하면서, maven-shade-plugin와 maven-dependency-plugin에 대해 공부를 하였다.

요약하자면, maven-dependency-plugin 은 의존성 JAR 파일을 추출하고 maven-shade-plugin 은

  • 의존성 파일들을 하나의 Jar로 모아 생성하고,
  • Manifest.MF에 Main 실행 경로를 선언하여 Jar 실행시 자동으로 선언한 Main클래스를 실행하는 역할을 수행한다.

Categories:

Updated: