Menu

#501 Keepclassmembers behaves differently based on class-specifier

v4.5
closed-works-for-me
None
5
2015-02-18
2014-03-15
Brian White
No

I originally tried to get help for this problem on StackOverflow but didn't get anything.
http://stackoverflow.com/questions/22418691/why-does-proguard-keepclassmembers-behave-differently-based-on-class-specifier

It seems like it may be a bug...

I've been debugging a ProGuard issue in an Android app I'm writing caused by it removing field names that are needed to extract the fields from a JSON string. To make sure those members remained with their original names, I added this:

-keepclassmembers class com.example.common.regions.** {
    !static !final !transient <fields>;
}

This seemed to work and the output mapping.txt showed the following:

com.example.common.regions.RegionMapMeta -> com.example.b.d.b:
java.lang.String mapVid -> mapVid
int mapVersion -> mapVersion
double topLeftLat -> topLeftLat
double topLeftLong -> topLeftLong
double topRightLat -> topRightLat
double topRightLong -> topRightLong
double bottomLeftLat -> bottomLeftLat
double bottomLeftLong -> bottomLeftLong
double bottomRightLat -> bottomRightLat
double bottomRightLong -> bottomRightLong
double boundingTopLat -> boundingTopLat
double boundingBottomLat -> boundingBottomLat
double boundingLeftLong -> boundingLeftLong
double boundingRightLong -> boundingRightLong
int minZoom -> minZoom
int maxZoom -> maxZoom
int maxZoomMinX -> maxZoomMinX
int maxZoomMaxX -> maxZoomMaxX
int maxZoomMinY -> maxZoomMinY
int maxZoomMaxY -> maxZoomMaxY
int stackOrder -> stackOrder
java.lang.String thumbnailImage -> thumbnailImage
java.util.Set mapLayers -> mapLayers

Then I thought I didn't like having to specify directories in ProGuard and that it would be better to have an annotation to distinguish these classes.

@Target(ElementType.TYPE)
public @interface ProguardKeepClassMembers {
}

I then annotated my classes (not the members, just the classes) with @ProguardKeepClassMembers and changed the ProGuard rule to be as such:

-keepclassmembers @com.example.common.ProguardKeepClassMembers class * {
    !static !final !transient <fields>;
}

However, this does not work the same. The mapping.txt file has the same fields but now they're being obfuscated.

com.example.common.regions.RegionMapMeta -> com.example.b.d.b:
java.lang.String mapVid -> a
int mapVersion -> b
double topLeftLat -> c
double topLeftLong -> d
double topRightLat -> e
double topRightLong -> f
double bottomLeftLat -> g
double bottomLeftLong -> h
double bottomRightLat -> i
double bottomRightLong -> j
double boundingTopLat -> k
double boundingBottomLat -> l
double boundingLeftLong -> m
double boundingRightLong -> n
int minZoom -> o
int maxZoom -> p
int maxZoomMinX -> q
int maxZoomMaxX -> r
int maxZoomMinY -> s
int maxZoomMaxY -> t
int stackOrder -> u
java.lang.String thumbnailImage -> v
java.util.Set mapLayers -> w

So... Why is -keepclassmembers behaving different when only the class matcher has changed?

Discussion

  • Eric Lafortune

    Eric Lafortune - 2014-03-15

    ProGuard is probably removing the annotation itself, since the code is not using it. You should keep it:

    -keep @interface com.example.common.ProguardKeepClassMembers
    

    Alternatively, you can collect such annotations in a jar annotations.jar and specify it as a library (without leaving it in the source code or in libs):

    -libraryjars annotations.jar
    

    The annotation classes then won't be in the resulting code, which is fine. This is the approach from the example examples/annotations/examples.pro (e.g. in android-sdk/tools/proguard).

    Also see the ProGuard manual > Troubleshooting > Unexpected observations after processing > Classes or class members not being kept.

     
  • Eric Lafortune

    Eric Lafortune - 2014-03-15
    • status: open --> closed-works-for-me
    • assigned_to: Eric Lafortune
     

Log in to post a comment.