记录:因为JDK编译版本问题,遇到的Base64的坑

4,610 阅读2分钟
今天遇到了一个BASE64Decoder的问题,记录一下。
报错异常信息:
  • Caused by: java.lang.NoClassDefFoundError: sun/misc/BASE64Decoder
一顿百度之后,发现根本原因是JDK版本从1.8之后就不再支持sun.misc.BASE64Encoder。那么解决方法很简单,找到一个合适的包,换掉import 引用。


难点:
引用BASE64Encoder的这个方法是源码级别的方法,没有办法直接修改引用。

再一顿百度。。发现使用Javassist 可以直接创建 .class文件,那么只要用这个工具创建出.class 进行包的替换,重新打包就可以解决。
首先用反编译工具打开需要编译的包,找到具体调用BASE64Decoder的方法
找到具体方法,这就是需要替换的类


用Javassist编写,执行main方法,代码编译版本会变成现有指定版本。




 ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("com.timevale.esign.sdk.file.LocalFileServiceImpl");
        Base64.Encoder b64encoder = Base64.getEncoder();
        CtMethod method = cc.getDeclaredMethod("signPdf"
                ,new CtClass[]{pool.get("com.tsign.tgpdfsign.signature.Signature"),pool.get("java.lang.String"),pool.get("java.lang.String"),pool.get("java.lang.String"),pool.get("[B")}
                );
        method.setBody(" {\n" +
                "        try {\n" +
                "            if (!esign.util.StringUtil.isNull($4) && this.signImpl.setReader($4, \"\") > 0) {\n" +
                "                return new com.timevale.esign.result.file.SignPDFResult(1045, esign.constant.ErrorConstant.getErrMsg(1045));\n" +
                "            } else if (this.signImpl.GetPageNum() > 300) {\n" +
                "                return new com.timevale.esign.result.file.SignPDFResult(1052, esign.constant.ErrorConstant.getErrMsg(1052));\n" +
                "            } else if (esign.util.StringUtil.isNull($4) && this.signImpl.setReaderByte($5) > 0) {\n" +
                "                return new com.timevale.esign.result.file.SignPDFResult(1046, esign.constant.ErrorConstant.getErrMsg(1046));\n" +
                "            } else if (this.signImpl.SetSignatureInfo($1.ToSignXMLString()) > 0) {\n" +
                "                return new com.timevale.esign.result.file.SignPDFResult(1047, esign.constant.ErrorConstant.getErrMsg(1047));\n" +
                "            } else if (this.signImpl.CreateSignStamper() > 0) {\n" +
                "                return new com.timevale.esign.result.file.SignPDFResult(1048, esign.constant.ErrorConstant.getErrMsg(1048));\n" +
                "            } else {\n" +
                "                byte[] fileContentBytes = this.signImpl.GetFileContentBytes();\n" +
                "                byte[] result = null;\n" +
                "                java.security.MessageDigest md = java.security.MessageDigest.getInstance(DEFAULT_DIGEST.name());\n" +
                "                md.update(fileContentBytes);\n" +
                "                byte[] result = md.digest();\n" +
                "                java.util.Base64.Encoder b64encoder = java.util.Base64.getEncoder();\n" +
                "                String hashB64 = b64encoder.encodeToString(result);\n" +
                "                $1.setHashB64(hashB64);\n" +
                "                esign.model.File file = new esign.model.File();\n" +
                "                if (!esign.util.StringUtil.isNull(this.code)) {\n" +
                "                    file.setLoginCode(this.code);\n" +
                "                }\n" +
                "\n" +
                "                com.timevale.esign.result.sign.CountersignResult countersign;\n" +
                "                  $1.setSignatureAlgorithm(com.tsign.tgpdfsign.config.SystemConfig.SignatureAlgorithm.SGD_SM3_SM2);\n" +
                "                                   countersign = this.signHashByZJCA($2, $3, $1.getHashB64());\n" +
                "                                   if (countersign.getErrCode() != 0) {\n" +
                "                                       $1.setSignatureAlgorithm(com.tsign.tgpdfsign.config.SystemConfig.SYSTEM_SIGN_ALGORITHM);\n" +
                "                                       countersign = this.signHash($2, $3, $1.getHashB64());\n" +
                "                                       if (countersign.getErrCode() != 0) {\n" +
                "                                           return new com.timevale.esign.result.file.SignPDFResult(countersign.getErrCode(), esign.constant.ErrorConstant.getErrMsg(countersign.getErrCode()));\n" +
                "                                       }\n" +
                "\n" +
                "                                       $1.setSignResult(countersign.getSignResult());\n" +
                "                                   } else {\n" +
                "                                       $1.setSignResult(countersign.getSignResult());\n" +
                "                                   }\n" +
                "\n" +
                "                if (org.apache.commons.lang.StringUtils.isNotBlank(esign.util.Oauth2Config.tsa_url)) {\n" +
                "                    if (this.signImpl.AddSignData($1.getSignResult(), $1.getHashB64(), esign.util.Oauth2Config.tsa_url) > 0) {\n" +
                "                        return new com.timevale.esign.result.file.SignPDFResult(1050, esign.constant.ErrorConstant.getErrMsg(1050));\n" +
                "                    }\n" +
                "                } else if (this.signImpl.AddSignData($1.getSignResult(), $1.getHashB64()) > 0) {\n" +
                "                    return new com.timevale.esign.result.file.SignPDFResult(1050, esign.constant.ErrorConstant.getErrMsg(1050));\n" +
                "                }\n" +
                "\n" +
                "                $1.setSignDate(this.signImpl.GetSignDate());\n" +
                "                this.outByte = this.signImpl.GetOutputByte();\n" +
                "                esign.bean.SignLogBean bean = new esign.bean.SignLogBean();\n" +
                "                String docName = this.signImpl.getFieldName();\n" +
                "                bean.setDocName(docName);\n" +
                "                bean.setSid($1.getSid());\n" +
                "                bean.setSignInfo($1.getSignResult());\n" +
                "                bean.setTimestamp($1.getSignDate());\n" +
                "                com.timevale.esign.sdk.sign.SignLogService signLogService = new com.timevale.esign.sdk.sign.SignLogServiceImpl();\n" +
                "                if (org.apache.commons.lang.StringUtils.isNotBlank(this.code)) {\n" +
                "                    signLogService.setLoginCode(this.code);\n" +
                "                }\n" +
                "\n" +
                "                com.timevale.esign.result.BaseResult signLogResult = signLogService.save($2, bean);\n" +
                "                return signLogResult != null && signLogResult.getErrCode() <= 0 ? new com.timevale.esign.result.file.SignPDFResult(0, esign.constant.ErrorConstant.getErrMsg(0)) : new com.timevale.esign.result.file.SignPDFResult(1054, esign.constant.ErrorConstant.getErrMsg(1054));\n" +
                "            }\n" +
                "        } catch (Exception var16) {\n" +
                "            var16.printStackTrace();\n" +
                "            return null;\n" +
                "        }\n" +
                "    }");

        cc.writeFile("C:\\输出文件路径");

代码比对:

这只是其中一个报错的方法,前前后后修改了好几个类好几个方法才把这个问题改好。。

附上参考的Javassist 教程: