java 如何告诉 proguard 保持枚举常量和字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33189249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 21:19:21  来源:igfitidea点击:

How to tell proguard to keep enum constants and fields

javaproguardobfuscation

提问by Hubbitus

I've try obfuscate our web application which use spring, jaxb and relies on annotations, and reflection heavily. I apply many recipes found in internet to keep some classes, attributes, annotations and enumerations. But with enumerations still have problem. I've able preserve enum constants apply configuration from http://proguard.sourceforge.net/manual/examples.html#enumerations:

我尝试混淆使用 spring、jaxb 并严重依赖注释和反射的 Web 应用程序。我应用了许多在互联网上找到的食谱来保留一些类、属性、注释和枚举。但是枚举仍然有问题。我已经能够从http://proguard.sourceforge.net/manual/examples.html#enumerations保留枚举常量应用配置:

-keepclassmembers,allowoptimization enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

At first glance it looks like working solution and constant preserved, so (Class.getEnumConstants()) return correct list of values. But I got NoSuchFieldException when I try retrieve field by any of that by name.

乍一看,它看起来像是有效的解决方案和常量,因此(Class.getEnumConstants())返回正确的值列表。但是当我尝试按名称中的任何一个检索字段时,我得到了 NoSuchFieldException。

Problem come from jaxb reflection navigator, please look at code:

问题来自jaxb 反射导航器,请看代码:

public Field[] getEnumConstants(Class clazz) {
    try {
        Object[] values = clazz.getEnumConstants();
        Field[] fields = new Field[values.length];
        for (int i = 0; i < values.length; i++) {
            fields[i] = clazz.getField(((Enum) values[i]).name());
        }
        return fields;
    } catch (NoSuchFieldException e) {
        // impossible
        throw new NoSuchFieldError(e.getMessage());
    }
}

I fall exactly into "impossible" branch. I think it will be easy understandable to look at debug session screenshot (there also listed constants): Screenshot of debug session1

我完全属于“不可能”的分支。我认为查看调试会话屏幕截图很容易理解(还列出了常量): 调试会话 1 的屏幕截图

And if I try obtain fields, they are listed obfuscated as a, b, c, d, e, f: Screenshot of debug session2

如果我尝试获取字段,它们会被混淆为 a、b、c、d、e、f: 调试会话 2 的屏幕截图

My proguard configuration now look like (strip out some library listing and kipp particular classes, fields and methods about proguard complain):

我的 proguard 配置现在看起来像(去掉一些关于 proguard 抱怨的库列表和 kipp 特定的类、字段和方法):

-injars  core-3.15.rc5.6.jar
-outjars core-3.15.rc5.6.proguard.jar

-libraryjars <java.home>/lib/rt.jar

-libraryjars ... # Other libs listed, strip out for shortness

-printmapping core-3.15.rc5.6.proguard.map

-keep public class ru.rlh.egais.portal.backend.controller.rest.**
-keep public class ru.rlh.egais.portal.backend.integration.soap.service.**

# http://midgetontoes.com/blog/2015/06/26/tips-for-using-proguard-with-spring-framework
-optimizations !class/marking/final

-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF,META-INF/spring.*,spring/*

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# Also tried:
# -keepattributes **

-allowaccessmodification
-dontshrink
-dontoptimize
-dontusemixedcaseclassnames
-keepdirectories
-keep @org.springframework.transaction.annotation.Transactional class *
-keep @org.springframework.stereotype.Service class *
-keep @org.springframework.stereotype.Repository class *
-keep @org.springframework.stereotype.Controller class *
-keep @org.springframework.stereotype.Component class *
-keep @org.springframework.beans.factory.annotation.Autowired class *
-keep @org.springframework.web.bind.annotation.ResponseBody class *
-keep @org.springframework.web.bind.annotation.RequestMapping class *
-keep @org.springframework.stereotype.Repository class *
-keep @javax.annotation.Resource class *
-keep @org.springframework.cache.annotation.EnableCaching class *
-keep @org.springframework.context.annotation.Configuration class *

-keepclassmembers class * {
    @org.springframework.beans.factory.annotation.* *;
    @org.springframework.beans.factory.annotation.Qualifier *;
    @org.springframework.beans.factory.annotation.Value *;
    @org.springframework.beans.factory.annotation.Required *;
    @org.springframework.context.annotation.Bean *;
    @javax.annotation.PostConstruct *;
    @javax.annotation.PreDestroy *;
    @org.aspectj.lang.annotation.AfterReturning *;
    @org.aspectj.lang.annotation.Pointcut *;
    @org.aspectj.lang.annotation.AfterThrowing *;
    @org.aspectj.lang.annotation.Around *;
}

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

So, my question how I could fully keep public enums from obfuscation? In both cases - use its constants (class.getEnumConstants()) and fields (class.getFields()).

那么,我的问题是如何才能完全避免公共枚举被混淆?在这两种情况下 - 使用其常量(class.getEnumConstants())和字段(class.getFields())。

回答by Hubbitus

Thanks to http://sourceforge.net/p/proguard/discussion/182455/thread/1c28f199/I found solution for my question (<?fields>must be added):

感谢http://sourceforge.net/p/proguard/discussion/182455/thread/1c28f199/我找到了我的问题的解决方案(必须添加<?fields>):

-keepclassmembers class * extends java.lang.Enum {
    <fields>;
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

回答by Joma

This worked fine for me.

这对我来说很好。

-keep public enum com.company.appname.**{
    *;
}

Where ** is package and subpackages.

其中 ** 是包和子包。