jvm运行时内存溢出

2018-11-13  本文已影响0人  笑才
image.png
image.png

JVM运行时数据区
一、 线程私有的数据区

程序计数器

作用 :记录当前线程所执行到的字节码的行号。字节码解释器工作的时候就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
意义 :JVM的多线程是通过线程轮流切换并分配处理器来实现的,对于我们来说的并行事实上一个处理器也只会执行一条线程中的指令。所以,为了保证各线程指令的安全顺利执行,每条线程都有独立的私有的程序计数器。
存储内容 :
        当线程中执行的是一个Java方法时,程序计数器中记录的是正在执行的线程的虚拟机字节码指令的地址。 
当线程中执行的是一个本地方法时,程序计数器中的值为空。
可能出现异常 :此内存区域是唯一一个在JVM上不会发生内存溢出异常(OutOfMemoryError)的区域。

虚拟机栈

作用 :描述Java方法执行的内存模型。每个方法在执行的同时都会开辟一段内存区域用于存放方法运行时所需的数据,成为栈帧,一个栈帧包含如:局部变量表、操作数栈、动态链接、方法出口等信息。
意义 :JVM是基于栈的,所以每个方法从调用到执行结束,就对应着一个栈帧在虚拟机栈中入栈和出栈的整个过程。
存储内容 :局部变量表(编译期可知的各种基本数据类型、引用类型和指向一条字节码指令的returnAddress类型)、操作数栈、动态链接、方法出口等信息。 
值得注意的是:局部变量表所需的内存空间在编译期间完成分配。在方法运行的阶段是不会改变局部变量表的大小的。
可能出现的异常 :
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。 
如果在动态扩展内存的时候无法申请到足够的内存,就会抛出OutOfMemoryError异常。

本地方法栈

作用 :为JVM所调用到的Nativa即本地方法服务。
可能出现的异常 :和虚拟机栈出现的异常很相像。
    二、所有线程共有的数据区
Java堆

作用 :所有线程共享一块内存区域,在虚拟机开启的时候创建。
意义: 
1、存储对象实例,更好地分配内存。 
2、垃圾回收(GC)。堆是垃圾收集器管理的主要区域。更好地回收内存。 
-存储内容 :存放对象实例,几乎所有的对象实例都在这里进行分配。堆可以处于物理上不连续的内存空间,只要逻辑上是连续的就可以。 
值得注意的是:在JIT编译器等技术的发展下,所有对象都在堆上进行分配已变得不那么绝对。有些对象实例也可以分配在栈中。
可能出现的异常 :
实现堆可以是固定大小的,也可以通过设置配置文件设置该为可扩展的。 
如果堆上没有内存进行分配,并无法进行扩展时,将会抛出OutOfMemoryError异常。

方法区

作用 :用于存储运行时常量池、已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
意义 :对运行时常量池、常量、静态变量等数据做出了规定。
存储内容 :运行时常量池(具有动态性)、已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
可能出现的异常 :当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

内存泄露:被分配的对象可达但不无用
长生命周期的对象持有短生命周期的对象
修改了hashset中对象的参数值,并且这个参数是参与计算哈希值的 计算
内存溢出:无法申请到足够的内存二导致的一种错误
OutOfMemoryError: java heap space(堆内存溢出)
当你看到heap相关的时候就肯定是堆栈溢出了,此时如果代码没有问题的情况下,适当调整-Xmx和-Xms是可以避免的,不过一定是代码没有问题的前提,为什么会溢出呢,要么代码有问题,要么访问量太多并且每个访问的时间太长或者数据太多,导致数据释放不掉,因为垃圾回收器是要找到那些是垃圾才能回收,这里它不会认为这些东西是垃圾,自然不会去回收了
OutOfMemoryError: permGen space(方法区溢出)
原因:系统的代码非常多或引用的第三方包非常多、或代码中使用了大量的常量、或通过intern注入常量、或者通过动态代码加载等方法,导致常量池的膨胀,虽然JDK 1.5以后可以通过设置对永久带进行回收,但是我们希望的是这个地方是不做GC的,它够用就行,所以一般情况下尽量少做类似的操作,所以在面对这种情况常用的手段是:增加-XX:PermSize和-XX:MaxPermSize的大小。
java.lang.stackOverflowError(栈溢出)
这个参数直接说明一个内容,就是-Xss太小了,我们申请很多局部调用的栈针等内容是存放在用户当前所持有的线程中的,线程在jdk 1.4以前默认是256K,1.5以后是1M,如果报这个错,只能说明-Xss设置得太小,当然有些厂商的JVM不是这个参数,本文仅仅针对Hotspot VM而已;不过在有必要的情况下可以对系统做一些优化,使得-Xss的值是可用的,设置示例:-Xss2m;
java.lang.OutOfMemoryError:GC over head limit exceeded
(当系统处于高频的GC状态,而且回收的效果依然不佳的情况,就会开始报这个错误,这种情况一般是产生了很多不可以被释放的对象,有可能是引用使用不当导致,或申请大对象导致,但是java heap space的内存溢出有可能提前不会报这个错误,也就是可能内存就直接不够导致,而不是高频GC.)
java.lang.OutOfMemoryError: unable to create new native thread
上面第四种溢出错误,已经说明了线程的内存空间,其实线程基本只占用heap以外的内存区域,也就是这个错误说明除了heap以外的区域,无法为线程分配一块内存区域了,这个要么是内存本身就不够,要么heap的空间设置得太大了,导致了剩余的内存已经不多了,而由于线程本身要占用内存,所以就不够用了
java.lang.OutOfMemoryError: request {} byte for {}out of swap
这类错误一般是由于地址空间不够而导致

避免内存溢出
尽早释放无用对象
处理字符串的时候,尽可能使用stringBuffer 每一个String对象都占一个独立内存
尽量少用静态变量,静态变量存放在方法区
避免在循环中创建对象

本文参照:https://www.cnblogs.com/zhouyuqin/p/5161677.html

上一篇 下一篇

猜你喜欢

热点阅读