You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中Proguard混淆类未加入Jar包问题求助

Spring Boot 3.2.5 + Java 21 混淆后Jar包丢失应用类问题

我正在为Spring Boot 3.2.5(Java 21)应用的Jar包做混淆处理,初始Jar和混淆后的Jar都已生成,但混淆Jar里没有包含应用包内的类。ProGuard映射文件proguard_map.txt中能看到应用类已被混淆,但最终Jar里找不到这些类,怀疑是打包流程或顺序问题,求解决。


环境信息

  • Spring Boot 3.2.5
  • Java 21
  • ProGuard 7.3.2
  • proguard-maven-plugin 2.6.1

我的ProGuard配置

# Obfuscation settings
-useuniqueclassmembernames
-classobfuscationdictionary obfuscation-dictionary.txt
-packageobfuscationdictionary obfuscation-dictionary.txt

# General options
-verbose
-dontoptimize
-dontshrink
-dontpreverify
-allowaccessmodification
-adaptclassstrings
-keepdirectories
-ignorewarnings

# Keep annotations
-keepattributes *Annotation*
-keepattributes Signature
-keepattributes Exceptions

# Keep main classes
-keep public class * extends    org.springframework.boot.web.support.SpringBootServletInitializer
-keep public class com.my.package.Application {
public static void main(java.lang.String[]);
}

-keep,allowobfuscation class com.my.package.Application.** { *; }
-keep interface com.my.package.** { *; }

-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}

# If you use Lombok, you might need this
-keep class lombok.** { *; }
-dontwarn lombok.**
-keepclassmembers class * {
@lombok.Setter *;
@lombok.Getter *;
@lombok.Cleanup *;
@lombok.ToString *;
@lombok.EqualsAndHashCode *;
@lombok.AllArgsConstructor *;
@lombok.NoArgsConstructor *;
@lombok.Builder *;
}

# Keep all classes in specific packages
-keep class my.package.** { *; }
-keep class org.springframework.boot.** { *; }
-keep class org.springframework.boot.loader.** { *; }
-dontwarn org.springframework.boot.loader.**

# Keep Spring Boot specific classes
-keep class org.springframework.boot.loader.jar.** { *; }
-keep class org.springframework.boot.loader.zip.** { *; }
-keep class java.util.jar.JarFile { *; }

# Keep ZIP related classes
-keep class java.util.zip.** { *; }
-dontwarn java.util.zip.**

# Keep all subclasses of InputStream
-keep class * extends java.io.InputStream { *; }
-keep class * extends java.util.zip.InflaterInputStream { *; }

# Keep specific classes and their inner classes
-keep class org.springframework.boot.loader.jar.NestedJarFile { *; }
-keep class org.springframework.boot.loader.jar.NestedJarFile$* { *; }
-keep class org.springframework.boot.loader.jar.ZipInflaterInputStream { *; }
-keep class org.springframework.boot.loader.zip.ZipContent$Entry { *; }

# Keep specific methods and fields
-keepclassmembers class * {
@org.springframework.beans.factory.annotation.Autowired *;
@org.springframework.beans.factory.annotation.Qualifier *;
@org.springframework.beans.factory.annotation.Value *;
@org.springframework.beans.factory.annotation.Required *;
@org.springframework.context.annotation.Bean *;
@org.springframework.context.annotation.Primary *;
@org.springframework.boot.context.properties.ConfigurationProperties *;
@org.springframework.boot.context.properties.EnableConfigurationProperties *;
@javax.inject.Inject *;
@javax.annotation.PostConstruct *;
@javax.annotation.PreDestroy *;
@org.springframework.security.access.prepost.PreAuthorize *;
}

# Keep enums
-keepclassmembers enum * {
    *;
}

# Keep Serializable classes
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

# Keep getters and setters
-keepclassmembers class * {
*** get*();
void set*(***);
}

# Keep specific annotations
-keep @org.springframework.cache.annotation.EnableCaching class *
-keep @org.springframework.context.annotation.Configuration class *
-keep @org.springframework.boot.context.properties.ConfigurationProperties class *
-keep @org.springframework.boot.autoconfigure.SpringBootApplication class *

# Keep specific directories
-keepdirectories org.springframework.boot.autoconfigure

Maven插件配置

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>3.2.5</version>
    <executions>
        <execution>
            <id>repackage</id>
            <phase>package</phase>
            <goals>
                <goal>repackage</goal>
            </goals>
            <configuration>
                <mainClass>com.my.package.Application</mainClass>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>com.github.wvengen</groupId>
    <artifactId>proguard-maven-plugin</artifactId>
    <version>2.6.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>proguard</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <proguardVersion>7.3.2</proguardVersion>
        <injar>${project.build.finalName}.jar</injar>
        <outjar>${project.build.finalName}-obfuscated.jar</outjar>
        <obfuscate>true</obfuscate>
        <proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
        <libs>
            <lib>${java.home}/lib/jrt-fs.jar</lib>
        </libs>
        <options>
            <option>-verbose</option>
        </options>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>com.guardsquare</groupId>
            <artifactId>proguard-base</artifactId>
            <version>7.3.2</version>
        </dependency>
    </dependencies>
</plugin>

调试日志片段

[proguard]   Number of obfuscated classes:                  41
 [proguard]   Number of obfuscated fields:                   196
 [proguard]   Number of obfuscated methods:                  121

解决方案

1. 调整Maven插件执行顺序

Spring Boot的repackage目标会生成嵌套结构的可执行Jar,ProGuard直接处理该Jar无法正确识别应用类。需让ProGuard先处理原始非可执行Jar,再由Spring Boot插件重新打包混淆后的Jar:

  • 修改ProGuard插件的执行阶段为prepare-package(早于package阶段的repackage):
    <execution>
        <phase>prepare-package</phase>
        <goals>
            <goal>proguard</goal>
        </goals>
    </execution>
    
  • 调整Spring Boot插件,指定混淆后的Jar作为输入:
    <configuration>
        <mainClass>com.my.package.Application</mainClass>
        <inputJar>${project.build.directory}/${project.build.finalName}-obfuscated.jar</inputJar>
        <outputJar>${project.build.directory}/${project.build.finalName}-obfuscated-exec.jar</outputJar>
    </configuration>
    

2. 修正ProGuard包名配置错误

配置中-keep class my.package.** { *; }缺少com前缀,与应用实际包名com.my.package不符,导致应用类未被正确保留,修改为:

-keep,allowobfuscation class com.my.package.** { *; }

3. 明确ProGuard输入源

确保ProGuard处理的是编译后的类文件而非可执行Jar,在ProGuard插件配置中指定输入为target/classes:

<injar>${project.build.directory}/classes</injar>

4. 保留应用类目录

在ProGuard配置中明确添加应用包目录的保留规则:

-keepdirectories com/my/package

验证步骤

  1. 执行mvn clean package,查看ProGuard日志确认应用类被正常处理
  2. 解压混淆后的Jar,检查BOOT-INF/classes目录下是否存在混淆后的应用类
  3. 运行最终的可执行混淆Jar,确认应用能正常启动

内容的提问来源于stack exchange,提问作者Marius D.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 00:12:34