【无标题】内存泄漏和内存溢出

一、内存泄漏
Java是有GC回收机制,理论上来说没有被GC root对象(本地方法栈、虚拟机栈、方法区)引用的对象就会被作为垃圾回收,但是实际情况中会有一些场景下对象不会被回收,这就是内存泄漏,久而久之当未能被回收的对象越来越多时就会造成内存溢出。
那么哪些场景下会造成内存泄漏呢,有以下几种:
1.静态容器中的对象,如HashMap、List等,当静态容器持有对象引用时虽然长时间不用,但一直不会被回收;简单来说就是长生命周期的对象持有短生命周期对象的引用就有可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收。
2.单例模式引用的对象,单例的生命周期和应用程序是一样长的,如果持有对外部对象的引用的话,那么这个外部对象就不能被回收,这样就导致了内存泄漏。
3.各种连接对象(IO流对象、数据库连接对象、网络连接对象)未关闭,如IO流对象、数据库连接对象、网络连接对象属于物理连接,和硬盘或网络连接,不使用的时候一定要关闭。
4.使用ThreadLocal进行线程隔离时,未及时remove掉线程的资源,导致内存泄漏。
二、内存溢出
内存溢出即用于存储信息的区域存满了,当添加新的内容时就会发生内存溢出问题。
内存溢出分为以下几种:
1.堆内存溢出
这部分内存主要是用来存储new出来的对象的信息(而它的引用就是它的地址信息,存储在虚拟机栈的局部变量表中)
java.lang.OutOfMemoryError: Java heap space ->这是最常见的内存溢出问题;
解决:
一是对于这类问题解决可以通过检查代码,是否出现循环new语句,可以通过一些分析工具来检测各个类的内存占用情况来判断
二是扩大堆区存储可以添加JVM参数 -Xms(初始堆内存)和-Xmx(最大堆内存)
2.栈内存溢出
这里栈的溢出不是OOM而是java.lang.StackOverflowError;
解决:
一是查询是否因为程序死循环或者发生递归深度过大(即未设置递归结束条件)。
二是栈大小设置过小,可以通过JVM参数-Xss来设置栈的大小。
3.方法区内存溢出
方法区主要存放的是Class类信息和静态变量(引用在方法区,但是信息存放在堆中),如果存放过多的类或者采用cglib代理会产生大量的Class信息在方法区,使得空间溢出。
方法区溢出可以通过设置方法区大小参数 ,这里需要注意1.6之前方法区是使用永久代实现,1.7时StringTable(字符串常量池)和静态变量放入了堆中,1.8方法区通过元空间来实现,在直接内存中存放,使用系统内存来尽可能防止方法区溢出
-XX:MetaspaceSize 来设置默认大小 -XX:MaxMetaspaceSize=-1表示没有限制
设置初始大小时,对于一个64位的服务器端JVM来说,其默认的21MB,初始高水位线,一旦触及,就会发生Full GC,然后高水位线重置,新的值取决于GC后释放了多少元空间,如果释放的不多就升高高水位线,如果释放的很多,就降低该值
-XX:MaxMetaspaceSize最大大小。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值