记一次报错:java.lang.OutOfMemoryError: Java heap space的解决方式

出现该报错条件:接口返回数据量比较大,然后对数据进行了SM4加密,所导致的报错。
网上常规解决思路:java虚拟机内存不够,修改jvm的启动参数。

-Xms258m -Xmx2048m

确实可以解决该问题,当我把内存放到4096M时,我的报错消失了。但是,问题随之而来,如果我的数据量更大时。是不是需要继续扩容呢?这虽然是一种解决方式,但可能有更好的解决方式。
于是,我重新定位问题,首先是我的加密写法如下

@PostMapping("/encrypt/sm4")
    public ResultWrapper sm4(@RequestBody EncryptInfo encryptInfo) throws Exception {
        String data = encryptInfo.getData();
        String key = encryptInfo.getKey();
        log.info("sm4加密参数data:{},key:{}", data, key);
        byte[] dataBytes = Base64.decodeBase64(data);
        byte[] keyBytes = Base64.decodeBase64(key);
        byte[] encrypt = Sm4Util.encrypt(keyBytes, dataBytes);
        return ResultWrapper.success(ByteUtils.toHexString(encrypt));
    }

最终问题是出在了ByteUtils.toHexString这个方法上,包内的方法写法是用位运算实现的

public static String toHexString3(byte[] bytes) {
  char[] buf = new char[bytes.length * 2];
  int index = 0;
  // 利用位运算进行转换
  for (byte b : bytes) {
    buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
    buf[index++] = HEX_CHAR[b & 0xf];
  }
  return new String(buf);
}

然后,我自定义了该方法,通过字符串拼接实现,如下

public static String toHexString(byte[] bytes) {
  StringBuilder sb = new StringBuilder();
  int num;
  for (byte b : bytes) {
    num = b < 0 ? 256 + b : b;
    sb.append(HEX_CHAR[num / 16]).append(HEX_CHAR[num % 16]);
  }
  return sb.toString();
}

最终解决了该问题。
java byte数组与16进制间相互转换参考博客:https://www.jb51.net/article/198049.htm

有一个疑问还未解决:位运算主要是直接操控二进制时使用 ,主要目的是节约内存,使你的程序速度更快,但为何我使用位运算方法的转换出现了溢出,反而使用字符串拼接的方法能够正常走完流程

总结:记录该问题并不是因为,这个bug有多难,更关键的是其中的思路转变,不要为了解决问题而去解决问题,去寻找到问题的根源,要对症下药,提醒自己以后如何面对新的问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值