Hubbitus Hubbitus - 1 month ago 7
Java Question

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

-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


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

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

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


Thanks to I found solution fo my question (<‚Ā†fields> must be added):

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