应该是从java G1开始就没有具体的老年代了。

但是在工作中由于使用的是老的GC形式。还是出现了这个问题。下面记录一下自己发现问题,解决问题的方法。

 

  1. 首先下载生产环境dump
  2. 使用jvisual 打开dump。老年代持续过高,可能有两个原因
    1. 大对象过多。如果对象太大,会直接分配到老年代
    2. 代码中有leak,造成资源无法回收。
  3. 拿到dump后,看到了有很多 byte 数组过大。看了一下内容,是上传附件的内容导致的。下面是第一版上传附件的后端代码。

java老年代过多

由于需要调用其他服务,所以要把request格式进行转化,不能直接透传。所以用到了ByteArrayResource。应该是转化成了这个地方转化的byte数组。没有及时的进行回收。

 

开始解决

方案一:

  1. 最开始打算查看http协议,直接用outputstream,直接写需要的数据。主要为了,不用读取字节数组。然后通过stream copy 减少内存使用。后来写了一点就放弃了。有点麻烦。
  2. 然后看了一下源代码,发现使用的是ByteArrayResource。我想直接使用其他的Resource代替就好了,应该有已经实现的这种累。然后找到了InputStreamResource。替换了以后,发现报错.do not use InputStreamResource if a stream needs to be read multiple times
  3. 我查看了一下代码,我应该没有使用InputStreamResource读取过内容。后来找了一篇帖子发现,AbstractResource读取长度的时候会调用inputSteam,代码如下。
  4. java老年代过多

  知道问题,然后避免读取inputStream就好了。重写 contentLeagth 方法。试了一下果然好用。

java老年代过多

 

然后打开-XX:+PrintGC 。发现内存果然会减少。

实际效果,还得等到上线以后才可以查看效果。

 

 

相关文章:

  • 2021-09-24
  • 2021-11-18
  • 2021-11-18
  • 2022-12-23
  • 2021-07-29
  • 2022-12-23
  • 2022-12-23
  • 2021-12-04
猜你喜欢
  • 2022-12-23
  • 2021-04-14
  • 2021-04-19
  • 2021-12-02
  • 2021-05-07
相关资源
相似解决方案