内存模型
1. PC寄存器 Program Counter Register
严格来说是一种数据结构,用于保存当前正常执行的程序的内存地址,来保证中断时只能能继续执行下去。
根据jvm规范,在这个区域中不会抛出OutOfMemoryError的内存异常。
2. Java栈 Java stack
这个区域是最容易出现内存异常的区域,每一个线程对应生成一个线程栈,线程每执行一个方法的时候,都会创建一个栈帧(Frames),用来存放方法的局部变量表,操作栈,动态连接,方法返回值等信息。
jvm规范对这个区域定义了两种内存异常,OutOfMemoryError,StackOverflowError。
命令设置方式:
-Xss
3. 本地方法栈 Native Method Stack
和虚拟机栈一样,不同的是处理的对象不一样,虚拟机栈处理java的字节码,而本地栈则是处理的Native方法。其他方面一致。
命令设置方式:
-XX:PermSize=2M
-XX:MaxPermSize=2M
4. 堆 Heap
堆是所有线程都能访问的,随着虚拟机的启动而存在,这块区域很大,因为所有的线程都在这个区域保存实例化的对象,因为每一个类型中,每个接口实现类需要的内存不一样,一个方法内的多个分支需要的内存也不尽相同,我们只有在运行的时候才能知道要创建多少对象,需要分配多大的地址空间。
GC关注的正是这样的部分内容,所以很多时候也将堆称为GC堆。
堆中肯定不会抛出StackOverflowError类型的异常,所以只有OutOfMemoryError相关类型的异常。
命令设置方式:
-Xms(堆的最小值)
-Xmx(堆的最大值)
5. 方法区 Method Area
用于存放已被虚拟机加载的类信息,常量,静态方法,即使编译后的代码。
同样只能抛出OutOfMemoryError相关类型的异常。
内存问题
1. 内存溢出 out of memory
定义:是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
原因:
- 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
- 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
- 代码中存在死循环或循环产生过多重复的对象实体;
- 使用的第三方软件中的BUG;
- 启动参数内存值设定的过小。
2. 内存泄露 memory leak
是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
参考:
1. 《深入分析 Java Web技术内幕》 许令波
2. 《Java高并发编程详解》 汪文君
3. 《内存溢出的解决思路》 www.cnblogs.com/200911/p/39…