今天遇到了一个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 教程: