Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell proguard to keep enum constants and fields

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:

-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.

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

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

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

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

-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()).

like image 786
Hubbitus Avatar asked Oct 17 '15 17:10

Hubbitus


People also ask

Is it better to use enum or constant?

Enums are lists of constants. When you need a predefined list of values which do represent some kind of numeric or textual data, you should use an enum. You should always use enums when a variable (especially a method parameter) can only take one out of a small set of possible values.

Can enums have fields?

The enum declaration defines a class (called an enum type). The enum class body can include methods and other fields.

Can we add constants to enum without breaking existing code?

4) Adding new constants on Enum in Java is easy and you can add new constants without breaking the existing code.

Should enums always be caps?

Enums are a type and the enum name should start with a capital. Enum members are constants and their text should be all-uppercase.


Video Answer


2 Answers

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

-keepclassmembers class * extends java.lang.Enum {     <fields>;     public static **[] values();     public static ** valueOf(java.lang.String); } 
like image 128
Hubbitus Avatar answered Sep 28 '22 09:09

Hubbitus


This worked fine for me.

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

Where ** is package and subpackages.

like image 43
Joma Avatar answered Sep 28 '22 11:09

Joma