{"id":418,"date":"2017-11-14T20:13:00","date_gmt":"2017-11-15T01:13:00","guid":{"rendered":"http:\/\/jebware.com\/blog\/?p=418"},"modified":"2017-11-14T20:13:00","modified_gmt":"2017-11-15T01:13:00","slug":"distinguishing-between-the-different-proguard-keep-directives","status":"publish","type":"post","link":"https:\/\/jebware.com\/blog\/?p=418","title":{"rendered":"Distinguishing between the different ProGuard \u201c-keep\u201d directives"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">If you search for ProGuard rules for a Java or Android library, you\u2019ll see a lot of answers on StackOverflow that tell you to do something like this:<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">-keep class com.foo.library.** { *; } <\/span><\/pre>\n<p><span style=\"font-weight: 400;\">That advice is really bad, and you should never do it. \u00a0First, it\u2019s overly broad &#8212; that double-asterisk in the package means every class under every package under that top-level package; and the asterisk inside the curly braces applies to every member (variables, methods, and constants) inside those class. \u00a0That is, it applies to all code in the library. \u00a0If you use that rule, Jake Wharton is going to come yell at you:<\/span><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/Screen-Shot-2017-11-14-at-10.08.20-AM.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-419\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/Screen-Shot-2017-11-14-at-10.08.20-AM.png\" alt=\"\" width=\"770\" height=\"123\" \/><\/a><\/p>\n<p><span style=\"font-weight: 400;\">Second, and what this post is about, is the beginning of the directive, that \u201c-keep\u201d. \u00a0<\/span><b><i>You almost never want to use -keep<\/i><\/b><span style=\"font-weight: 400;\">; if you do need a ProGuard rule, you usually want one of the more specific variants below. \u00a0But it always takes me a minute with the ProGuard manual to figure out which one of those variants applies to my case, so I made some tables for quick visual reference. \u00a0(Quick aside: <a href=\"https:\/\/www.guardsquare.com\/en\/proguard\/manual\/introduction\">the ProGuard manual<\/a><\/span><span style=\"font-weight: 400;\">\u00a0is very useful and I highly recommend you look through it.)<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">No rule<\/span><\/h3>\n<p><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/none.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-421\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/none.png\" alt=\"\" width=\"399\" height=\"397\" \/><\/a><\/p>\n<p><span style=\"font-weight: 400;\">To get our bearings, let\u2019s look at the default. \u00a0If you don\u2019t specify a keep directive of any kind, then ProGuard is going to do it\u2019s normal thing &#8212; it\u2019s going to both <\/span><i><span style=\"font-weight: 400;\">shrink<\/span><\/i><span style=\"font-weight: 400;\"> (i.e. remove unused code) and <\/span><i><span style=\"font-weight: 400;\">obfuscate<\/span><\/i><span style=\"font-weight: 400;\"> (i.e. rename things) both classes and class members.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">-keep<\/span><\/h3>\n<p><span style=\"font-weight: 400;\"><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/keep.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-422\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/keep.png\" alt=\"\" width=\"397\" height=\"397\" \/><\/a><\/span><\/p>\n<p><span style=\"font-weight: 400;\">See, this is why I said you should almost never use -keep. \u00a0-keep disables all of ProGuard\u2019s goodness. \u00a0No shrinking, no obfuscation; not for classes, not for members. \u00a0In real use cases, you can let ProGuard do at least <\/span><i><span style=\"font-weight: 400;\">some<\/span><\/i><span style=\"font-weight: 400;\"> of it\u2019s work. \u00a0Even if your variables are accessed by reflection, you could remove and rename unused classes, for example. \u00a0So let\u2019s look through the more specific -keep variants.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">-keepclassmembers<\/span><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/keepclassmembers.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-423\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/keepclassmembers.png\" alt=\"\" width=\"397\" height=\"397\" \/><\/a><\/h3>\n<p><span style=\"font-weight: 400;\">This protects only the members of the class from shrinking and obfuscation. \u00a0That is, if a class is unused, it will be removed. \u00a0If the class is used, the class will be kept but renamed. \u00a0But inside any class that is kept around, all of its members will be there, and they will have their original names.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">-keepnames<\/span><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/keepnames.png\"><br \/>\n<img loading=\"lazy\" class=\"aligncenter size-full wp-image-424\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/keepnames.png\" alt=\"\" width=\"397\" height=\"397\" \/><\/a><\/h3>\n<p><span style=\"font-weight: 400;\">This allows shrinking for classes and members, but not obfuscation. \u00a0That is, any unused code is going to get removed. \u00a0But the code that is kept will keep its original names.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">-keepclassmembernames<\/span><\/h3>\n<p><span style=\"font-weight: 400;\"><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/keepclassmembernames.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-425\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/keepclassmembernames.png\" alt=\"\" width=\"397\" height=\"397\" \/><\/a><\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is the most permissive keep directive; it lets ProGuard do <\/span><i><span style=\"font-weight: 400;\">almost<\/span><\/i><span style=\"font-weight: 400;\"> all of its work. \u00a0Unused classes are removed, the remaining classes are renamed, unused members of those classes are removed, but then the remaining members keep their original names.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">-keepclasseswithmembers<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">This one doesn\u2019t get a table, because it\u2019s the same as -keep. \u00a0The difference is that it only applies to classes who have all of the members in the class specification.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">-keepclasseswithmembernames<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">Similarly, this rule is the same as -keepnames. \u00a0The difference, again, is that it only applies to classes who have all of the members in the class specification.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">Conclusion<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">You want to let ProGuard do as much work as possible, so pick the directive that has the fewest red X blocks above, while still meeting your need.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you search for ProGuard rules for a Java or Android library, you\u2019ll see a lot of answers on StackOverflow that tell you to do something like this: -keep class com.foo.library.** { *; } That advice is really bad, and you should never do it. \u00a0First, it\u2019s overly broad &#8212; that double-asterisk in the package &hellip; <a href=\"https:\/\/jebware.com\/blog\/?p=418\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Distinguishing between the different ProGuard \u201c-keep\u201d directives&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"twitterCardType":"summary_large_image","cardImageID":0,"cardImage":"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/11\/keepclassmembernames.png","cardTitle":"","cardDesc":"","cardImageAlt":"","cardPlayer":"","cardPlayerWidth":0,"cardPlayerHeight":0,"cardPlayerStream":"","cardPlayerCodec":""},"categories":[4,16],"tags":[],"_links":{"self":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/418"}],"collection":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=418"}],"version-history":[{"count":5,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/418\/revisions"}],"predecessor-version":[{"id":432,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/418\/revisions\/432"}],"wp:attachment":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=418"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=418"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}