今天遇到了一个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 教程:
javassist使用全解析 - rickiyang - 博客园