JVM内存及内存溢出异常(个人总结)

来源:互联网 发布:健身房锻炼软件 编辑:程序博客网 时间:2024/05/29 16:33

JVM内存溢出异常

    想了解Java虚拟机内存溢出异常就要先明白JVM内存有那些,它们都有什么作用,这样我们才能更加深入的理解内存溢出是怎么回事。
在JAVA虚拟机内存中运行时内存区域除了PC(线程私有区--程序计数器)不会发生OutOfMemoryError异常,其他几个区域[{线程共享区域:方法区、堆},{线程私有区:本地方法栈、虚拟机栈}]。
线程共享区域中----------------
-----------方法区:
它用于存放已经被虚拟机加载的类信息(object header info)、常量和JIT编译器编译后的代码等数据。
这个区域的内存回收目标是针对常量池的回收和类型的卸载。(运行时常量池-------Class文件中除了包括类的版本、字段、方法、接口等描述信息以外,还有一项信息是常量池信息,其中包括编译器生成的各种字面量和符号引用,在类被加载的时候就存到了方法区的运行时常量池中)。
-----------堆:
对大多数应用来说堆是内存管理中最大的一块,它主要存放对象实例信息。
它随着虚拟机的启动而产生,是垃圾回收管理的主要区域。
线程私有区域-------------------
----------虚拟机栈:
它的生命周期和线程相同。虚拟机栈描述的是 JAVA方法执行的内存模型:
每个方法执行的时候都会创建一个栈帧来存储局部变量表、操作数栈、动态链接、方法出口。每个方法调用直到执行完成的过程,都对应着栈帧在虚拟机中入栈到出栈的过程。
----------本地方法栈
本地方法栈和虚拟机栈发挥的作用是非常相似的,
虚拟机栈为虚拟机执行JAVA方法服务,而本地方法栈是为虚拟机使用到Native的方法服务。
----------程序计数器
程序计数器是内存区域中较小的一块区域,它可以看作是当前线程所执行的字节码的行号指示器。
字节码解释器工作时就是通过改变计数器的值来选取下一条所需要执行的字节指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

JVM内存溢出异常:
------------------------------------JAVA栈溢出
StackOverFlowError:
每当JAVA序启动一个新线程时,JAVA虚拟机会为它分配一个JAVA栈。
JAVA栈以帧为单位保存线程的运行状态。每当线程调用一个方法时,虚拟机压入一个栈帧到JAVA栈中。只要这个方法没有返回,那么它就会一直存在。如果线程嵌套的方法(没有返回)太多,随着栈帧的逐渐增多,JAVA栈中所有栈帧大小总和大于-Xss设置的值,就会出现StackOverFlowError异常。

eg:
public class Cx{
public void method(){
System.out.print("cx");
method();
}
main(String[] args){
new Cx().method();
}
}
方法递归,当方法过多就会出现异常。

OutOfMemoryError:
当JAVA程序启动一个新线程时,没有足够的内存空间为该线程分配JAVA栈(一个JAVA栈的大小由-Xss参数确定),JVM则抛出OutOfMemoryError异常。
eg:
public class Cx{
main(String[] args){
new Thread(new runable(){
public void run(){
System.out.print("....cx");
}
}).start();
}
}
-------------------------------------JAVA堆溢出
我们知道JAVA堆是用来存储对象实例的。那么JAVA堆溢出,说明了存放对象实例的空间不足了。
内存分配不够存储对象实例,就会出现OutOfMemoryError异常。
 
-------------------------------------JAVA方法区溢出
方法区用来存放JAVA类型的相关信息,如类名、访问修饰符、方法描述、字段描述等。
在类装载器加载class文件到内存的过程中,虚拟机会提取其中的信息,并将其保存到方法区中。运行时产生大量的类,当达到设置的内存值之后,就会溢出。
希望大家会有收获,如果有不对的地方希望留言指出。谢谢
0 0