title: Proguard obfuscation of Java8 method references breaks at runtime
body: <p>I am encountering a persistent problem when obfuscating java8 source code. Lambda method references seem to fail at runtime when they are used multiple times within a function.
  The failing code:</p>
  
  <pre><code>Set&lt;String&gt; roleNames = this.userDAO.getUserRoles(userDTO.getId()).stream().map(RoleDTO::getName).collect(Collectors.toSet());
  SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(roleNames);
  
  Set&lt;String&gt; permissions = this.userDAO.getUserPermissions(userDTO.getId()).stream().map(NameDescriptionDTO::getName).collect(Collectors.toSet());
  authorizationInfo.addStringPermissions(permissions);
  </code></pre>
  
  <p>This works fine when compiling with maven and java 8.0_40, however this fails when proguard has obfuscated the lib with the following stack trace:</p>
  
  <pre><code>org.jboss.weld.interceptor.proxy.InterceptorException: java.lang.BootstrapMethodError: call site initialization exception
  ~
  Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class package.db.dto.PermissionDTO; not a subtype of implementation type class package.db.dto.RoleDTO 
  at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233) ~[?:1.8.0_40]
  at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303) ~[?:1.8.0_40]
  at java.lang.invoke.CallSite.makeSite(CallSite.java:302) ~[?:1.8.0_40]
  at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307) ~[?:1.8.0_40]
  at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297) ~[?:1.8.0_40]
  at package.method(Unknown Source) ~[LIB.jar:?]
  </code></pre>
  
  <p>proguard-maven-plugin settings:</p>
  
  <pre><code>&lt;options&gt;
      &lt;option&gt;-dontshrink&lt;/option&gt;
      &lt;option&gt;-dontoptimize&lt;/option&gt;
      &lt;option&gt;-keepdirectories&lt;/option&gt;
      &lt;option&gt;-keepattributes Signature&lt;/option&gt;
      &lt;option&gt;-keepattributes *Annotation*&lt;/option&gt;
      &lt;option&gt;-keep public class * implements Foo&lt;/option&gt;
      &lt;option&gt;-keepclassmembers,allowshrinking,allowobfuscation class * { synthetic &amp;lt;methods&amp;gt;; }&lt;/option&gt;
  &lt;/options&gt;
  </code></pre>
  
  <p>Rewriting the code to use a lambda expression instead of the method reference format does seem to work, but as I use method references in numerous places throughout the source, this would only be a last resort solution:</p>
  
  <pre><code>Set&lt;String&gt; roleNames = this.userDAO.getRoles(userDTO.getId()).stream().map(r -&gt; r.getName()).collect(Collectors.toSet());   
  Set&lt;String&gt; permissions = this.userDAO.getPermissions(userDTO.getId()).stream().map(p -&gt; p.getName()).collect(Collectors.toSet());
  </code></pre>
  
  <p>I investigated the error message and it seems that there is JVM bug (<a href="https://stackoverflow.com/questions/27031244/lambdaconversionexception-with-generics-jvm-bug">LambdaConversionException with generics: JVM bug?</a>) which might be related.
  Using cfr_0_98 to decompile the obfuscated and unobfuscated java files does not show any obvious differences:
  Obfuscated output:</p>
  
  <pre><code>Set set = this.userDAO.a(userDTO.getId()).stream().map((Function&lt;package.db.dto.RoleDTO, String&gt;)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)Ljava/lang/Object;, getName(), (package/db/dto/RoleDTO;)Ljava/lang/String;)()).collect(Collectors.toSet());
  Set set2 = this.userDAO.c(userDTO.getId()).stream().map((Function&lt;package.db.dto.PermissionDTO, String&gt;)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)Ljava/lang/Object;, getName(), (Lpackage /db/dto/PermissionDTO;)Ljava/lang/String;)()).collect(Collectors.toSet());
  </code></pre>
  
  <p>Unobfuscated output (from other machine now more readable and also showing the problem. RoleDTO is incorrectly being used 2 times!):</p>
  
  <pre><code>Set set = this.userDAO.a(userDTO.getId()).stream().map(RoleDTO::getName).collect(Collectors.toSet());
  Set set2 = this.userDAO.c(userDTO.getId()).stream().map(RoleDTO::getName).collect(Collectors.toSet());
  </code></pre>
  
  <p>Any pointers would be very much appreciated on which Proguard flags might help us out.</p>
  
  <p>Edit:</p>
  
  <p>Here is the obfuscated bytecode disassembled (javap -v):</p>
  
  <pre><code>  Last modified 20-mrt-2015; size 3949 bytes
    MD5 checksum 1d3582e145d46fc813957931629413ff
  public class package.web.security.impl.DefaultSecurityRealm extends org.apache.shiro.realm.AuthorizingRealm
    BootstrapMethods:
      0: #63 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
        Method arguments:
          #93 (Ljava/lang/Object;)Ljava/lang/Object;
          #62 invokevirtual package/db/dto/RoleDTO.getName:()Ljava/lang/String;
          #95 (Lpackage/db/dto/RoleDTO;)Ljava/lang/String;
      1: #63 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
        Method arguments:
          #93 (Ljava/lang/Object;)Ljava/lang/Object;
          #62 invokevirtual package/db/dto/RoleDTO.getName:()Ljava/lang/String;
          #94 (Lpackage/db/dto/PermissionDTO;)Ljava/lang/String;
    minor version: 0
    major version: 52
    flags: ACC_PUBLIC, ACC_SUPER
  Constant pool:
      #1 = String             #132          //  Some String
      #2 = String             #135          //  Some String
      #3 = String             #137          //  Some String
      #4 = Class              #156          //  java/lang/Object
      #5 = Class              #157          //  java/lang/String
      #6 = Class              #158          //  java/lang/invoke/LambdaMetafactory
      #7 = Class              #159          //  java/util/List
      #8 = Class              #160          //  java/util/Set
      #9 = Class              #161          //  java/util/stream/Collectors
     #10 = Class              #162          //  java/util/stream/Stream
     #11 = Class              #165          //  package/db/K
     #12 = Class              #166          //  package/db/dto/NameDescriptionDTO
     #13 = Class              #167          //  package/db/dto/RoleDTO
     #14 = Class              #168          //  package/db/dto/UserDTO
     #15 = Class              #169          //  package/web/security/impl/DefaultSecurityRealm
     #16 = Class              #170          //  org/apache/commons/lang/StringUtils
     #17 = Class              #171          //  org/apache/shiro/authc/AccountException
     #18 = Class              #172          //  org/apache/shiro/authc/AuthenticationException
     #19 = Class              #173          //  org/apache/shiro/authc/AuthenticationToken
     #20 = Class              #174          //  org/apache/shiro/authc/SimpleAuthenticationInfo
     #21 = Class              #175          //  org/apache/shiro/authc/UnknownAccountException
     #22 = Class              #176          //  org/apache/shiro/authc/UsernamePasswordToken
     #23 = Class              #177          //  org/apache/shiro/authz/SimpleAuthorizationInfo
     #24 = Class              #178          //  org/apache/shiro/codec/Base64
     #25 = Class              #179          //  org/apache/shiro/realm/AuthorizingRealm
     #26 = Class              #180          //  org/apache/shiro/subject/PrincipalCollection
     #27 = Class              #181          //  org/apache/shiro/util/SimpleByteSource
     #28 = Class              #182          //  org/jooq/exception/DataAccessException
     #29 = Fieldref           #15.#92       //  package/web/security/impl/DefaultSecurityRealm.userDAO:Lpackage/db/K;
     #30 = Methodref          #5.#78        //  java/lang/String.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
     #31 = Methodref          #6.#89        //  java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
     #32 = Methodref          #9.#91        //  java/util/stream/Collectors.toSet:()Ljava/util/stream/Collector;
     #33 = Methodref          #12.#80       //  package/db/dto/NameDescriptionDTO.getName:()Ljava/lang/String;
     #34 = Methodref          #13.#80       //  package/db/dto/RoleDTO.getName:()Ljava/lang/String;
     #35 = Methodref          #14.#79       //  package/db/dto/UserDTO.getId:()Ljava/util/UUID;
     #36 = Methodref          #14.#81       //  package/db/dto/UserDTO.getPassword:()Ljava/lang/String;
     #37 = Methodref          #14.#83       //  package/db/dto/UserDTO.getSalt:()Ljava/lang/String;
     #38 = Methodref          #15.#76       //  package/web/security/impl/DefaultSecurityRealm.createSimpleAuthenticationInfo:(Ljava/lang/String;)Lorg/apache/shiro/authc/SimpleAuthenticationInfo;
     #39 = Methodref          #15.#80       //  package/web/security/impl/DefaultSecurityRealm.getName:()Ljava/lang/String;
     #40 = Methodref          #15.#85       //  package/web/security/impl/DefaultSecurityRealm.getUsername:(Lorg/apache/shiro/authc/UsernamePasswordToken;)Ljava/lang/String;
     #41 = Methodref          #16.#86       //  org/apache/commons/lang/StringUtils.isBlank:(Ljava/lang/String;)Z
     #42 = Methodref          #16.#87       //  org/apache/commons/lang/StringUtils.isNotBlank:(Ljava/lang/String;)Z
     #43 = Methodref          #17.#66       //  org/apache/shiro/authc/AccountException."&lt;init&gt;":(Ljava/lang/String;)V
     #44 = Methodref          #18.#67       //  org/apache/shiro/authc/AuthenticationException."&lt;init&gt;":(Ljava/lang/String;Ljava/lang/Throwable;)V
     #45 = Methodref          #20.#65       //  org/apache/shiro/authc/SimpleAuthenticationInfo."&lt;init&gt;":(Ljava/lang/Object;Ljava/lang/Object;Lorg/apache/shiro/util/ByteSource;Ljava/lang/String;)V
     #46 = Methodref          #21.#66       //  org/apache/shiro/authc/UnknownAccountException."&lt;init&gt;":(Ljava/lang/String;)V
     #47 = Methodref          #22.#84       //  org/apache/shiro/authc/UsernamePasswordToken.getUsername:()Ljava/lang/String;
     #48 = Methodref          #23.#68       //  org/apache/shiro/authz/SimpleAuthorizationInfo."&lt;init&gt;":(Ljava/util/Set;)V
     #49 = Methodref          #23.#72       //  org/apache/shiro/authz/SimpleAuthorizationInfo.addStringPermissions:(Ljava/util/Collection;)V
     #50 = Methodref          #24.#77       //  org/apache/shiro/codec/Base64.decode:(Ljava/lang/String;)[B
     #51 = Methodref          #25.#64       //  org/apache/shiro/realm/AuthorizingRealm."&lt;init&gt;":()V
     #52 = Methodref          #27.#69       //  org/apache/shiro/util/SimpleByteSource."&lt;init&gt;":([B)V
     #53 = InterfaceMethodref #7.#90        //  java/util/List.stream:()Ljava/util/stream/Stream;
     #54 = InterfaceMethodref #10.#75       //  java/util/stream/Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
     #55 = InterfaceMethodref #10.#88       //  java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
     #56 = InterfaceMethodref #11.#70       //  package/db/K.a:(Ljava/lang/String;)Lpackage/db/dto/UserDTO;
     #57 = InterfaceMethodref #11.#71       //  package/db/K.a:(Ljava/util/UUID;)Ljava/util/List;
     #58 = InterfaceMethodref #11.#74       //  package/db/K.c:(Ljava/util/UUID;)Ljava/util/List;
     #59 = InterfaceMethodref #26.#82       //  org/apache/shiro/subject/PrincipalCollection.getPrimaryPrincipal:()Ljava/lang/Object;
     #60 = InvokeDynamic      #0:#73        //  #0:apply:()Ljava/util/function/Function;
     #61 = InvokeDynamic      #1:#73        //  #1:apply:()Ljava/util/function/Function;
     #62 = MethodHandle       #5:#34        //  invokevirtual package/db/dto/RoleDTO.getName:()Ljava/lang/String;
     #63 = MethodHandle       #6:#31        //  invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
     #64 = NameAndType        #125:#102     //  "&lt;init&gt;":()V
     #65 = NameAndType        #125:#104     //  "&lt;init&gt;":(Ljava/lang/Object;Ljava/lang/Object;Lorg/apache/shiro/util/ByteSource;Ljava/lang/String;)V
     #66 = NameAndType        #125:#107     //  "&lt;init&gt;":(Ljava/lang/String;)V
     #67 = NameAndType        #125:#110     //  "&lt;init&gt;":(Ljava/lang/String;Ljava/lang/Throwable;)V
     #68 = NameAndType        #125:#114     //  "&lt;init&gt;":(Ljava/util/Set;)V
     #69 = NameAndType        #125:#124     //  "&lt;init&gt;":([B)V
     #70 = NameAndType        #138:#105     //  a:(Ljava/lang/String;)Lpackage/db/dto/UserDTO;
     #71 = NameAndType        #138:#115     //  a:(Ljava/util/UUID;)Ljava/util/List;
     #72 = NameAndType        #139:#113     //  addStringPermissions:(Ljava/util/Collection;)V
     #73 = NameAndType        #140:#99      //  apply:()Ljava/util/function/Function;
     #74 = NameAndType        #141:#115     //  c:(Ljava/util/UUID;)Ljava/util/List;
     #75 = NameAndType        #142:#117     //  collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
     #76 = NameAndType        #143:#106     //  createSimpleAuthenticationInfo:(Ljava/lang/String;)Lorg/apache/shiro/authc/SimpleAuthenticationInfo;
     #77 = NameAndType        #144:#109     //  decode:(Ljava/lang/String;)[B
     #78 = NameAndType        #147:#111     //  format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
     #79 = NameAndType        #148:#98      //  getId:()Ljava/util/UUID;
     #80 = NameAndType        #149:#97      //  getName:()Ljava/lang/String;
     #81 = NameAndType        #150:#97      //  getPassword:()Ljava/lang/String;
     #82 = NameAndType        #151:#96      //  getPrimaryPrincipal:()Ljava/lang/Object;
     #83 = NameAndType        #152:#97      //  getSalt:()Ljava/lang/String;
     #84 = NameAndType        #153:#97      //  getUsername:()Ljava/lang/String;
     #85 = NameAndType        #153:#122     //  getUsername:(Lorg/apache/shiro/authc/UsernamePasswordToken;)Ljava/lang/String;
     #86 = NameAndType        #154:#108     //  isBlank:(Ljava/lang/String;)Z
     #87 = NameAndType        #155:#108     //  isNotBlank:(Ljava/lang/String;)Z
     #88 = NameAndType        #163:#116     //  map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
     #89 = NameAndType        #164:#112     //  metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
     #90 = NameAndType        #184:#101     //  stream:()Ljava/util/stream/Stream;
     #91 = NameAndType        #185:#100     //  toSet:()Ljava/util/stream/Collector;
     #92 = NameAndType        #186:#134     //  userDAO:Lpackage/db/K;
     #93 = MethodType         #103          //  (Ljava/lang/Object;)Ljava/lang/Object;
     #94 = MethodType         #119          //  (Lpackage/db/dto/PermissionDTO;)Ljava/lang/String;
     #95 = MethodType         #120          //  (Lpackage/db/dto/RoleDTO;)Ljava/lang/String;
     #96 = Utf8               ()Ljava/lang/Object;
     #97 = Utf8               ()Ljava/lang/String;
     #98 = Utf8               ()Ljava/util/UUID;
     #99 = Utf8               ()Ljava/util/function/Function;
    #100 = Utf8               ()Ljava/util/stream/Collector;
    #101 = Utf8               ()Ljava/util/stream/Stream;
    #102 = Utf8               ()V
    #103 = Utf8               (Ljava/lang/Object;)Ljava/lang/Object;
    #104 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;Lorg/apache/shiro/util/ByteSource;Ljava/lang/String;)V
    #105 = Utf8               (Ljava/lang/String;)Lpackage/db/dto/UserDTO;
    #106 = Utf8               (Ljava/lang/String;)Lorg/apache/shiro/authc/SimpleAuthenticationInfo;
    #107 = Utf8               (Ljava/lang/String;)V
    #108 = Utf8               (Ljava/lang/String;)Z
    #109 = Utf8               (Ljava/lang/String;)[B
    #110 = Utf8               (Ljava/lang/String;Ljava/lang/Throwable;)V
    #111 = Utf8               (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
    #112 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    #113 = Utf8               (Ljava/util/Collection;)V
    #114 = Utf8               (Ljava/util/Set;)V
    #115 = Utf8               (Ljava/util/UUID;)Ljava/util/List;
    #116 = Utf8               (Ljava/util/function/Function;)Ljava/util/stream/Stream;
    #117 = Utf8               (Ljava/util/stream/Collector;)Ljava/lang/Object;
    #118 = Utf8               (Lpackage/db/K;)V
    #119 = Utf8               (Lpackage/db/dto/PermissionDTO;)Ljava/lang/String;
    #120 = Utf8               (Lpackage/db/dto/RoleDTO;)Ljava/lang/String;
    #121 = Utf8               (Lorg/apache/shiro/authc/AuthenticationToken;)Lorg/apache/shiro/authc/AuthenticationInfo;
    #122 = Utf8               (Lorg/apache/shiro/authc/UsernamePasswordToken;)Ljava/lang/String;
    #123 = Utf8               (Lorg/apache/shiro/subject/PrincipalCollection;)Lorg/apache/shiro/authz/AuthorizationInfo;
    #124 = Utf8               ([B)V
    #125 = Utf8               &lt;init&gt;
    #126 = Utf8               BootstrapMethods
    #127 = Utf8               Code
    #128 = Utf8               ConstantValue
    #129 = Utf8               EXCEPTION_ACCOUNT
    #130 = Utf8               EXCEPTION_AUTHENTICATION_DATASOURCE
    #131 = Utf8               EXCEPTION_UNKNOWN_ACCOUNT
    #132 = Utf8               Empty usernames are not allowed.
    #133 = Utf8               Ljava/lang/String;
    #134 = Utf8               Lpackage/db/K;
    #135 = Utf8               No account found for user [%s].
    #136 = Utf8               StackMapTable
    #137 = Utf8               There was a SQL error while authenticating user [%s].
    #138 = Utf8               a
    #139 = Utf8               addStringPermissions
    #140 = Utf8               apply
    #141 = Utf8               c
    #142 = Utf8               collect
    #143 = Utf8               createSimpleAuthenticationInfo
    #144 = Utf8               decode
    #145 = Utf8               doGetAuthenticationInfo
    #146 = Utf8               doGetAuthorizationInfo
    #147 = Utf8               format
    #148 = Utf8               getId
    #149 = Utf8               getName
    #150 = Utf8               getPassword
    #151 = Utf8               getPrimaryPrincipal
    #152 = Utf8               getSalt
    #153 = Utf8               getUsername
    #154 = Utf8               isBlank
    #155 = Utf8               isNotBlank
    #156 = Utf8               java/lang/Object
    #157 = Utf8               java/lang/String
    #158 = Utf8               java/lang/invoke/LambdaMetafactory
    #159 = Utf8               java/util/List
    #160 = Utf8               java/util/Set
    #161 = Utf8               java/util/stream/Collectors
    #162 = Utf8               java/util/stream/Stream
    #163 = Utf8               map
    #164 = Utf8               metafactory
    #165 = Utf8               package/db/K
    #166 = Utf8               package/db/dto/NameDescriptionDTO
    #167 = Utf8               package/db/dto/RoleDTO
    #168 = Utf8               package/db/dto/UserDTO
    #169 = Utf8               package/web/security/impl/DefaultSecurityRealm
    #170 = Utf8               org/apache/commons/lang/StringUtils
    #171 = Utf8               org/apache/shiro/authc/AccountException
    #172 = Utf8               org/apache/shiro/authc/AuthenticationException
    #173 = Utf8               org/apache/shiro/authc/AuthenticationToken
    #174 = Utf8               org/apache/shiro/authc/SimpleAuthenticationInfo
    #175 = Utf8               org/apache/shiro/authc/UnknownAccountException
    #176 = Utf8               org/apache/shiro/authc/UsernamePasswordToken
    #177 = Utf8               org/apache/shiro/authz/SimpleAuthorizationInfo
    #178 = Utf8               org/apache/shiro/codec/Base64
    #179 = Utf8               org/apache/shiro/realm/AuthorizingRealm
    #180 = Utf8               org/apache/shiro/subject/PrincipalCollection
    #181 = Utf8               org/apache/shiro/util/SimpleByteSource
    #182 = Utf8               org/jooq/exception/DataAccessException
    #183 = Utf8               setUserDAO
    #184 = Utf8               stream
    #185 = Utf8               toSet
    #186 = Utf8               userDAO
  {
    protected org.apache.shiro.authz.AuthorizationInfo doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection);
      descriptor: (Lorg/apache/shiro/subject/PrincipalCollection;)Lorg/apache/shiro/authz/AuthorizationInfo;
      flags: ACC_PROTECTED
      Code:
        stack=3, locals=6, args_size=2
           0: aload_1       
           1: invokeinterface #59,  1           // InterfaceMethod org/apache/shiro/subject/PrincipalCollection.getPrimaryPrincipal:()Ljava/lang/Object;
           6: checkcast     #14                 // class package/db/dto/UserDTO
           9: astore_2      
          10: aload_0       
          11: getfield      #29                 // Field userDAO:Lpackage/db/K;
          14: aload_2       
          15: invokevirtual #35                 // Method package/db/dto/UserDTO.getId:()Ljava/util/UUID;
          18: invokeinterface #57,  2           // InterfaceMethod package/db/K.a:(Ljava/util/UUID;)Ljava/util/List;
          23: invokeinterface #53,  1           // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
          28: invokedynamic #60,  0             // InvokeDynamic #0:apply:()Ljava/util/function/Function;
          33: invokeinterface #55,  2           // InterfaceMethod java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
          38: invokestatic  #32                 // Method java/util/stream/Collectors.toSet:()Ljava/util/stream/Collector;
          41: invokeinterface #54,  2           // InterfaceMethod java/util/stream/Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
          46: checkcast     #8                  // class java/util/Set
          49: astore_3      
          50: new           #23                 // class org/apache/shiro/authz/SimpleAuthorizationInfo
          53: dup           
          54: aload_3       
          55: invokespecial #48                 // Method org/apache/shiro/authz/SimpleAuthorizationInfo."&lt;init&gt;":(Ljava/util/Set;)V
          58: astore        4
          60: aload_0       
          61: getfield      #29                 // Field userDAO:Lpackage/db/K;
          64: aload_2       
          65: invokevirtual #35                 // Method package/db/dto/UserDTO.getId:()Ljava/util/UUID;
          68: invokeinterface #58,  2           // InterfaceMethod package/db/K.c:(Ljava/util/UUID;)Ljava/util/List;
          73: invokeinterface #53,  1           // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
          78: invokedynamic #61,  0             // InvokeDynamic #1:apply:()Ljava/util/function/Function;
          83: invokeinterface #55,  2           // InterfaceMethod java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
          88: invokestatic  #32                 // Method java/util/stream/Collectors.toSet:()Ljava/util/stream/Collector;
          91: invokeinterface #54,  2           // InterfaceMethod java/util/stream/Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
          96: checkcast     #8                  // class java/util/Set
          99: astore        5
         101: aload         4
         103: aload         5
         105: invokevirtual #49                 // Method org/apache/shiro/authz/SimpleAuthorizationInfo.addStringPermissions:(Ljava/util/Collection;)V
         108: aload         4
         110: areturn       
  }
  </code></pre>
  
  <p><strong>Update</strong></p>
  
  <p>We have moved to <a href="http://www.zelix.com/klassmaster/" rel="nofollow noreferrer">http://www.zelix.com/klassmaster/</a> for our obfuscation. Commercial, but it does work well with all Java 8 features. (I am not affiliated).</p>