ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

JVM 内存益出

2020-08-22 16:00:36  阅读:200  来源: 互联网

标签:益出 永久 大小 XX 内存 JVM 空间 溢出


内存溢出是什么?

当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出。

内存溢出和内存泄漏有什么区别?

内存泄漏是由于使用不当,把一部分内存“丢掉了”,导致这部分内存不可用。
当在堆中创建了对象,后来没有使用这个对象了,又没有把整个对象的相关引用设为null。此时垃圾收集器会认为这个对象是需要的,就不会清理这部分内存。这就会导致这部分内存不可用。
所以内存泄漏会导致可用的内存减少,进而会导致内存溢出

用到的jvm参数

下面为了说明溢出的情景,会执行一些实例代码,同时需要给jvm指定参数

  • -Xms 堆最小容量(heap min size)
  • -Xmx 堆最大容量(heap max size)
  • -Xss 栈容量(stack size)
  • -XX:PermSize=size 永生代最小容量
  • -XX:MaxPermSize=size 永生代最大容量

一 堆溢出

java.lang.OutOfMemoryError: Java heap space

这个异常是由于堆中存在大量的对象,这些对象无法通过垃圾回收进行收集从而导致的堆内存溢出,堆溢出呢,分为两种情况:

  • 内存泄露(大量无用的对象与根节点还具有管理,无法被回收)
  • 对象过多

如何解决?

  • 内存泄露情况可以通过工具找出泄露的具体代码然后进行优化
  • 对象太多可以适当根据机器的性能使用-Xms -Xmx等参数调整堆的大小
  • 优化数据结构,避免内存浪费

 

二 直接内存溢出

OutOfMemoryError

直接内存并不属于运行时数据区的一部分。但是也需要占用内存,如果我们在分配内存时把本机的总内存都分配给运行时数据区的各个部分而忽略了直接内存的话就会容易引起直接内存溢出。Java中使用直接内存最多的就是NIO。

如何解决?

  • 使用-XX:MaxDirectMemorySize属性指定直接内存的大小

 

三 方法区溢出

java.lang.OutOfMemoryError: PermGen space

因为方法区主要是负责存放类的相关信息,而且因为gc的次数也不像堆来的频繁,所以当class越来越多的时候就会引起此异常

如何解决?

  • 使用-XX:PermSize参数调整方法区的大小

 

四 虚拟机栈和本地方法栈(栈溢出)

StackOverflowError
由于线程请求的栈深度大于了线程所允许的最大深度而引起的

如何解决?

使用-Xss参数调整栈的大小
OutOfMemoryError: unable to create new native thread

当创建的线程多到栈的内存不足以支撑时就会引起此异常

如何解决?

使用-Xss参数调整栈的大小

五 Metaspace(元空间)

元空间这个东西,是在JDK8以后才存在的,JDK7及以前,只有永久代
元空间的存储位置是在计算机的内存当中,而永久的存储们置是在JVM的地堆中

JVM用元空间代替永久代的原因:
1随着操作系统的发展,计算机支持的内存从32位的最大2^32字节,变为64位的最大2^48字节。

2随着Java 在Web领域的发展,java程序变的得越来越大,需要加载的内容也越来越多,如果
使用永久代实现方法区,那么需要手动扩大堆的大小,而使用元空间之后,就可以直接存
储在内存当中,不用手动云修改堆的大小。

 元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:

  -XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
  -XX:MaxMetaspaceSize,最大空间,默认是没有限制的。

  除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:
  -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
  -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

 

大家应该大致了解了 JVM 的内存划分,也清楚了 JDK 8 中永久代向元空间的转换。不过大家应该都有一个疑问,就是为什么要做这个转换?所以,最后给大家总结以下几点原因:

  1、字符串存在永久代中,容易出现性能问题和内存溢出。

  2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。

  3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。

  4、Oracle 可能会将HotSpot 与 JRockit 合二为一。

标签:益出,永久,大小,XX,内存,JVM,空间,溢出
来源: https://www.cnblogs.com/shu-java-net/p/13545992.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有