这些 Java 8 官方挖的坑,你踩过几个?

导读:系统启动异常日志竟然被JDK吞噬无法定位?同样的加密方法 , 竟然出现部分数据解密失败?往List里面添加数据竟然提示不支持?日期明明间隔1年却输出1天 , 难不成这是天上人间?1582年神秘消失的10天JDK能否识别?Stream很高大上 , List转Map却全失败……这些JDK8官方挖的坑 , 你踩过几个?
1、Base64:你是我解不开的迷出于用户隐私信息保护的目的 , 系统上需将姓名、身份证、手机号等敏感信息进行加密存储 , 很自然选择了AES算法 , 外面又套了一层Base64 , 之前用的是sun.misc.BASE64Decoder/BASE64Encoder , 网上的资料基本也都是这种写法 , 运行得很完美 。
但这种写法在idea或者maven编译时就会有一些黄色告警提示 。到了JAVA 8后 , Base64编码已经成为Java类库的标准 , 内置了 Base64 编码的编码器和解码器 。于是乎 , 我手贱地修改了代码 , 改用了jdk8自带的Base64方法
import java.util.Base64;public class Base64Utils {    public static final Base64.Decoder DECODER = Base64.getDecoder();    public static final Base64.Encoder ENCODER = Base64.getDecoder();    public static String encodeToString(byte[] textByte) {        return ENCODER.encodeToString(textByte);    }    public static byte[] decode(String str) {        return DECODER.decode(str);    }}程序员的职业操守咱还是有的 , 构造新老数据、自测、通过 , 提交测试版本 。信心满满 , 我要继续延续我 0 Bug的神话!然后……然后版本就被打回了 。
Caused by: java.lang.IllegalArgumentException: Illegal base64 character 3f    at java.util.Base64$Decoder.decode0(Base64.java:714)    at java.util.Base64$Decoder.decode(Base64.java:526)    at java.util.Base64$Decoder.decode(Base64.java:549)关键是这个错还很诡异 , 部分数据是可以解密的 , 部分解不开 。
Base64依赖于简单的编码和解码算法 , 使用65个字符的US-ASCII子集 , 其中前64个字符中的每一个都映射到等效的6位二进制序列 , 第65个字符(=)用于将Base64编码的文本填充到整数大小 。后来产生了3个变种:

  • RFC 4648:Basic ,  此变体使用RFC 4648和RFC 2045的Base64字母表进行编码和解码 。编码器将编码的输出流视为一行; 没有输出行分隔符 。解码器拒绝包含Base64字母表之外的字符的编码 。
  • RFC 2045:MIME  , 此变体使用RFC 2045提供的Base64字母表进行编码和解码 。编码的输出流被组织成不超过76个字符的行; 每行(最后一行除外)通过行分隔符与下一行分隔 。解码期间将忽略Base64字母表中未找到的所有行分隔符或其他字符 。
  • RFC 4648:Url ,  此变体使用RFC 4648中提供的Base64字母表进行编码和解码 。字母表与前面显示的字母相同 , 只是-替换+和_替换/ 。不输出行分隔符 。解码器拒绝包含Base64字母表之外的字符的编码 。

这些 Java 8 官方挖的坑,你踩过几个?

文章插图
 
关于base64用法的详细说明 , 可参考:https://juejin.im/post/5c99b2976fb9a070e76376cc
对于上面的错误 , 网上有的说法是 , 建议使用Base64.getMimeDecoder()和Base64.getMimeEncoder() , 对此我只能建议:老的系统如果已经有数据了 , 就不要使用jdk自带的Base64了 。JDK官方的Base64和sun的base64是不兼容的!不要替换!不要替换!不要替换!
2、被吞噬的异常:我不敢说出你的名字这个问题理解起来还是蛮费脑子的 , 所以我把这个系统异常发生的过程提炼成了一个美好的故事 , 放松一下 , 吟诗一首!
最怕相思浓一切皆是你唯独不敢说出你的名字-- 马大叔
这个问题是在使用springboot的注解时遇到的 , 发现JDK在解析注解时 , 若注解依赖的类定义在JVM加载时不存在 , 也就是NoClassDefFoundError时 , 实际拿到的异常将会是ArrayStoreException , 而不是NoClassDefFoundError , 涉及到的JDK里的类是AnnotationParser.java, 具体代码如下:


推荐阅读