核心提示:原因有很多种,比如: 1.数据量过于庞大;死循环 ;静态变量和静态方法过多;递归;无法确定是否被引用的对象; 2.虚拟机不回收内存(内存泄漏); 说白了就是程序运行要用到的内存大于虚拟机能提供的最大内存就发生内存溢出了。 内存溢出的问题要看业务和系
原因有很多种,比如:
1.数据量过于庞大;死循环 ;静态变量和静态方法过多;递归;无法确定是否被引用的对象;
2.虚拟机不回收内存(内存泄漏);
说白了就是程序运行要用到的内存大于虚拟机能提供的最大内存就发生内存溢出了。 内存溢出的问题要看业务和系统大小而定,对于某些系统可能内存溢出不常见,但某些系统还是很常见的解决的方法,
一个是优化程序代码,如果业务庞大,逻辑复杂,尽量减少全局变量的引用,让程序使用完变量的时候释放该引用能够让垃圾回收器回收,释放资源。
二就是物理解决,增大物理内存,然后通过:-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m的修改
一、内存溢出类型
1 、 java.lang.OutOfMemoryError: PermGen space
JVM 管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在 JVM 启动时创建;非堆是留给 JVM 自己用的,用来存放类的信息的。它和堆不同,运行期内 GC 不会释放空间。如果 web app 用了大量的第三方 jar 或者应用有太多的 class 文件而恰好 MaxPermSize 设置较小,超出了也会导致这块内存的占用过多造成溢出,或者 tomcat 热部署时侯不会清理前面加载的环境,只会将 context 更改为新部署的,非堆存的内容就会越来越多。
2 、 java.lang.OutOfMemoryError: Java heap space
第一种情况是个补充,主要存在问题就是出现在这个情况中。其默认空间 ( 即 -Xms) 是物理内存的 1/64 ,最大空间 (-Xmx) 是物理内存的 1/4 。如果内存剩余不到 40 %, JVM 就会增大堆到 Xmx 设置的值,内存剩余超过 70 %, JVM 就会减小堆到 Xms 设置的值。所以服务器的 Xmx 和 Xms 设置一般应该设置相同避免每次 GC 后都要调整虚拟机堆的大小。假设物理内存无限大,那么 JVM 内存的最大值跟操作系统有关,一般 32 位机是 1.5g 到 3g 之间,而 64 位的就不会有限制了。
注意:如果 Xms 超过了 Xmx 值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。
垃圾回收 GC 的角色
JVM 调用 GC 的频度还是很高的,主要两种情况下进行垃圾回收:
当应用程序线程空闲;另一个是 java 内存堆不足时,会不断调用 GC ,若连续回收都解决不了内存堆不足的问题时,就会报 out of memory 错误
。因为这个异常根据系统运行环境决定,所以无法预期它何时出现。
根据 GC 的机制,
程序的运行会引起系统运行环境的变化,增加 GC 的触发机会。
为了避免这些
问题,程序的设计和编写就应避免垃圾对象的内存占用和 GC 的开销。显示调用 System.GC() 只能建议 JVM 需要在内存中对垃圾对象进行回收,但不是必须马上回收,
一个是并不能解决内存资源耗空的局面,另外也会增加 GC 的消耗。
二、 JVM 内存区域组成
简单的说 java中的堆和栈
java把内存分两种:一种是栈内存,另一种是堆内存
1。在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;
2。堆内存用来存放由 new创建的对象和数组
在函数(代码块)中定义一个变量时, java就在栈中为这个变量分配内存空间,当超过变量的作用域后, java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由 java虚拟机的自动垃圾回收器来管理
堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢;
栈的优势是存取速度比堆要快,缺点是存在栈中的数据大