Java8方法引用的Proguard混淆在运行时中断 [英] Proguard obfuscation of Java8 method references breaks at runtime

查看:180
本文介绍了Java8方法引用的Proguard混淆在运行时中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在混淆java8源代码时遇到了持久性问题。 Lambda方法引用在函数中多次使用时似乎在运行时失败。
失败的代码:

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:

Set<String> roleNames = this.userDAO.getUserRoles(userDTO.getId()).stream().map(RoleDTO::getName).collect(Collectors.toSet());
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(roleNames);

Set<String> permissions = this.userDAO.getUserPermissions(userDTO.getId()).stream().map(NameDescriptionDTO::getName).collect(Collectors.toSet());
authorizationInfo.addStringPermissions(permissions);

在使用maven和java 8.0_40进行编译时这很好用,但是当proguard混淆了lib时这会失败使用以下堆栈跟踪:

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:

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:?]

proguard-maven-plugin设置:

proguard-maven-plugin settings:

<options>
    <option>-dontshrink</option>
    <option>-dontoptimize</option>
    <option>-keepdirectories</option>
    <option>-keepattributes Signature</option>
    <option>-keepattributes *Annotation*</option>
    <option>-keep public class * implements Foo</option>
    <option>-keepclassmembers,allowshrinking,allowobfuscation class * { synthetic &lt;methods&gt;; }</option>
</options>

重写代码以使用lambda表达式而不是方法引用格式似乎有效,但是我在整个源代码的许多地方使用方法引用,这只是最后的解决方案:

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:

Set<String> roleNames = this.userDAO.getRoles(userDTO.getId()).stream().map(r -> r.getName()).collect(Collectors.toSet());   
Set<String> permissions = this.userDAO.getPermissions(userDTO.getId()).stream().map(p -> p.getName()).collect(Collectors.toSet());

我调查了错误消息,似乎有JVM错误(LambdaConversionException with generics:JVM bug?)可能是相关的。
使用cfr_0_98反编译混淆和未混淆的java文件没有显示任何明显的差异:
混淆输出:

I investigated the error message and it seems that there is JVM bug (LambdaConversionException with generics: JVM bug?) which might be related. Using cfr_0_98 to decompile the obfuscated and unobfuscated java files does not show any obvious differences: Obfuscated output:

Set set = this.userDAO.a(userDTO.getId()).stream().map((Function<package.db.dto.RoleDTO, String>)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<package.db.dto.PermissionDTO, String>)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)Ljava/lang/Object;, getName(), (Lpackage /db/dto/PermissionDTO;)Ljava/lang/String;)()).collect(Collectors.toSet());

未经模糊处理的输出(来自其他机器现在更具可读性并且还显示问题.RightsDTO被错误地使用2次!):

Unobfuscated output (from other machine now more readable and also showing the problem. RoleDTO is incorrectly being used 2 times!):

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

任何指针都非常受欢迎,Proguard旗帜可以帮助我们。

Any pointers would be very much appreciated on which Proguard flags might help us out.

编辑:

以下是反汇编的混淆字节码(javap -v):

Here is the obfuscated bytecode disassembled (javap -v):

  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."<init>":(Ljava/lang/String;)V
   #44 = Methodref          #18.#67       //  org/apache/shiro/authc/AuthenticationException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
   #45 = Methodref          #20.#65       //  org/apache/shiro/authc/SimpleAuthenticationInfo."<init>":(Ljava/lang/Object;Ljava/lang/Object;Lorg/apache/shiro/util/ByteSource;Ljava/lang/String;)V
   #46 = Methodref          #21.#66       //  org/apache/shiro/authc/UnknownAccountException."<init>":(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."<init>":(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."<init>":()V
   #52 = Methodref          #27.#69       //  org/apache/shiro/util/SimpleByteSource."<init>":([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     //  "<init>":()V
   #65 = NameAndType        #125:#104     //  "<init>":(Ljava/lang/Object;Ljava/lang/Object;Lorg/apache/shiro/util/ByteSource;Ljava/lang/String;)V
   #66 = NameAndType        #125:#107     //  "<init>":(Ljava/lang/String;)V
   #67 = NameAndType        #125:#110     //  "<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
   #68 = NameAndType        #125:#114     //  "<init>":(Ljava/util/Set;)V
   #69 = NameAndType        #125:#124     //  "<init>":([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               <init>
  #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."<init>":(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       
}

更新

我们已移至我们的混淆 http://www.zelix.com/klassmaster/ 。商业,但它确实适用于所有Java 8功能。 (我不隶属于。)

We have moved to http://www.zelix.com/klassmaster/ for our obfuscation. Commercial, but it does work well with all Java 8 features. (I am not affiliated).

推荐答案

在原始的 BootstrapMethods 属性中

BootstrapMethods:
    0: #141 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:
        #142 (Ljava/lang/Object;)Ljava/lang/Object;
        #143 invokevirtual package/db/dto/RoleDTO.getName:()Ljava/lang/String;
        #144 (Lpackage/db/dto/RoleDTO;)Ljava/lang/String;
    1: #141 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:
        #142 (Ljava/lang/Object;)Ljava/lang/Object;
        #155 invokevirtual package/db/dto/NameDescriptionDTO.getName:()Ljava/lang/String;
        #156 (Lpackage/db/dto/PermissionDTO;)Ljava/lang/String;

两个条目都指向不同的目标方法。你清楚地看到#143 invokevirtual ... RoleDTO.getName #155 invokevirtual ... NameDescriptionDTO.getName ;这两个参数对应于bootstrap方法的 implMethod 参数

both entries point to different target methods. You see clearly #143 invokevirtual … RoleDTO.getName and #155 invokevirtual … NameDescriptionDTO.getName; these two arguments correspond to the implMethod parameter of the bootstrap method

metafactory(caller,invokedName,invokedType,samMethodType,implMethod,instantiatedMethodType)

相比之下,在混淆的类' BootstrapMethods 属性

In contrast, in the obfuscated class’ BootstrapMethods attribute

  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;

两个条目都指向完全相同的目标方法#62 invokevirtual ... RoleDTO。 getName

both entries refer to exactly the same target method #62 invokevirtual … RoleDTO.getName.

所以混淆器在这里进行了语义变换,我想这是Proguard中的一个错误。 JRE在拒绝调用时是正确的,因为最后一个条目仍然请求函数签名(PermissionDTO)String 但是想要将它链接到目标方法 RoleDTO .getName 具有功能签名(RoleDTO)字符串 PermissionDTO 不能分配给 RoleDTO (这正是消息所说的)。

So the obfuscator made a semantic changing transformation here, I guess it’s a bug in Proguard. The JRE is correct in rejecting the call as the last entry still requests the functional signature (PermissionDTO)String but wants to link it to the target method RoleDTO.getName which has the functional signature (RoleDTO)String and PermissionDTO can’t be assigned to RoleDTO (that’s exactly what the message says).

这篇关于Java8方法引用的Proguard混淆在运行时中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆