背景:自从将项目推到服务器之后,差不多每隔一段时间就会没办法访问页面。看了日志后才发现是内存溢出了。
今天摸这点差不多就是快溢出的日志,看了一次jvm。
这边可以看到我的老年代都99.85,感觉差一点就要溢出了。正好可以把他放在JavaVisualVM里面去排查一下。
按视频看到还有一个插件-arthas;
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
heapdump /tmp/hh.hprof
通过这个打印出一个快照。下载到电脑本地后,就可以在JavaVisualVM中打开相对应的文件。
可以看出我的实例总数真的很大,可能是我某个对象一直没删掉,然后导致内存满了。
打开类选项,可以看到我的ConCurrentHashMap的实例个数和大小占的最多,那就应该是这边出了问题吧。
在下面点击显示最近的垃圾回收根节点
可以看到那个应该要回收的节点类型。
this - value: java.util.concurrent.ConcurrentHashMap$Node #1
<- [0] - class: java.util.concurrent.ConcurrentHashMap$Node[], value: java.util.concurrent.ConcurrentHashMap$Node #1
<- table - class: java.util.concurrent.ConcurrentHashMap, value: java.util.concurrent.ConcurrentHashMap$Node[] #1
<- map - class: org.apache.http.config.Registry, value: java.util.concurrent.ConcurrentHashMap #1
<- authSchemeRegistry - class: org.apache.http.impl.client.InternalHttpClient, value: org.apache.http.config.Registry #1
<- httpClient - class: com.aliyun.oss.common.comm.DefaultServiceClient, value: org.apache.http.impl.client.InternalHttpClient #1
<- this$0 - class: com.aliyun.oss.common.comm.DefaultServiceClient$CompositeX509TrustManager, value: com.aliyun.oss.common.comm.DefaultServiceClient #60419
<- tm - class: sun.security.ssl.AbstractTrustManagerWrapper, value: com.aliyun.oss.common.comm.DefaultServiceClient$CompositeX509TrustManager #60419
<- trustManager - class: sun.security.ssl.SSLContextImpl$TLSContext, value: sun.security.ssl.AbstractTrustManagerWrapper #60420
<- context - class: sun.security.ssl.SSLSocketFactoryImpl, value: sun.security.ssl.SSLContextImpl$TLSContext #60420
<- socketfactory - class: org.apache.http.conn.ssl.SSLConnectionSocketFactory, value: sun.security.ssl.SSLSocketFactoryImpl #60421
<- val - class: java.util.concurrent.ConcurrentHashMap$Node, value: org.apache.http.conn.ssl.SSLConnectionSocketFactory #60420
<- [11] - class: java.util.concurrent.ConcurrentHashMap$Node[], value: java.util.concurrent.ConcurrentHashMap$Node #903163
<- table - class: java.util.concurrent.ConcurrentHashMap, value: java.util.concurrent.ConcurrentHashMap$Node[] #181692
<- map - class: org.apache.http.config.Registry, value: java.util.concurrent.ConcurrentHashMap #363312
<- socketFactoryRegistry - class: org.apache.http.impl.conn.DefaultHttpClientConnectionOperator, value: org.apache.http.config.Registry #181261
<- connectionOperator - class: org.apache.http.impl.conn.PoolingHttpClientConnectionManager, value: org.apache.http.impl.conn.DefaultHttpClientConnectionOperator #60420
<- [58934] - class: java.lang.Object[], value: org.apache.http.impl.conn.PoolingHttpClientConnectionManager #60420
<- elementData - class: java.util.ArrayList, value: java.lang.Object[] #169659
<- connectionManagers - class: com.aliyun.oss.common.comm.IdleConnectionReaper, value: java.util.ArrayList #16210
<- <class> (thread object) - class: com.aliyun.oss.common.comm.IdleConnectionReaper, value: com.aliyun.oss.common.comm.IdleConnectionReaper class IdleConnectionReaper
复制出根节点后可以发现com.aliyun.oss相关的jar包。那这样就可以怀疑是oss那边出了问题。
想的是是不是我开起来ossClient,但是并没有关闭它。就直接回去看代码了。
然后我每次想要去讲图片的桶名和文件名编译成ossUrl,都要访问这个接口,我的量很大的,所以就有很多的ossclient没有被关闭,最后导致我的内存被占满了。
解决方案就是讲上图中那个ossclient.shutdown()注释打开就好了。
nohup java -jar -Xms512M -Xmx512M -XX:PermSize=512M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/dump academy-1.0-SNAPSHOT.jar &
改完之后,并设置参数,要是出现异常问题就进行快照处理。等一下出现问题了。
暂时先记录一下。
使用arthas的dashboard可以一秒钟看一下最新的jvm中各个年代相对应的使用率。