Java8方法引用的Proguard混淆在运行时中断 [英] Proguard obfuscation of Java8 method references breaks at runtime
问题描述
我在混淆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 <methods>; }</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屋!