Java和C++之间有一堵由内存管理和垃圾收集技术所围成的“高墙”,墙外的人想进去,墙内的人却想出来。 ------摘自《深刻理解Java虚拟机》程序员
做为一个Java程序员,由于虚拟机的好处,在开发过程当中通常不用关心内存分配和垃圾回收方面的内容,这就让我在跟C++的朋友聊天或沟通的时候,总以为本身是个假的程序员,虽然咱们不用本身动手去作这两件事情,但仍是颇有必要去了解一下这方面的原理,这样万一真碰到内存溢出的问题,就不至于一筹莫展了。下面是经过看书总结的一些内容。数组
1、Java内存区域划分数据结构
Java虚拟机在执行Java程序的过程当中,会把它所管理的内存区域划分红不一样的数据区域,没有数据区域都有各自的功能、建立和销毁时间,有些随着虚拟机的启动而产生,有些随着用户线程的建立和结束而产生和销毁,根据《Java虚拟机规范》的规定,Java虚拟机所管理的内存将会包含下面几个部分:spa
从上图可知,Java虚拟机内存主要由线程共享的堆内存、方法区和线程私有的虚拟机栈、本地方法栈和程序计数器五个运行时数据区。线程
2、各运行时数据区的功能介绍对象
一、程序计数器内存
1)程序计数器是当前线程所执行的字节码的行号指示器,存放下一个要执行的字节码位置;开发
2)此内存区域是惟一一个在Java虚拟机规范中没有任何OutOfMemoryError异常的区域;编译器
3)线程私有虚拟机
二、Java虚拟机栈
1)Java虚拟机栈是方法执行的内存模型,通俗点说就是执行方法是进行内存管理的区域。
方法执行时,会建立一个栈帧,用于存储方法中的局部变量、操做数、动态连接和方法出口等信息,方法的调用执行过程就是一个栈帧在虚拟机栈中进行入栈出栈的过程;
2)线程私有,随着线程的开始而建立,线程的结束而销毁;
3)一般所说的Java栈内存就是指Java虚拟机栈中的局部变量表,它存放了编译期可知的基本类型(boolean、byte、char、short、int、long、float、dounle)、对象引用和returnAddress类型。局部变量的大小在程序编译期就已经完成,并且在方法执行期间不会被改变;
4)此区域可能发生的异常有:
StackOverflowError:当线程请求的栈深度超过Java虚拟机所容许的栈深度时,会发生栈溢出异常;
OutOFMemoryError:当虚拟机栈在动态扩展过程当中没有申请到足够的内存时,会发生内存溢出异常;
三、本地方法栈
1)同虚拟机栈,本地方法栈也是Java方法执行的内存模型,区别在于虚拟机栈是为Java程序在虚拟机中执行服务的,而本地方法栈是为本地方法在Java虚拟机中执行服务的。在虚拟机规范中,对本地方法栈中的方法所使用的语言、使用方法和数据结构都没有强制规定;
2)线程私有
3)可抛出两种异常:
StackOverflowError:当线程请求的栈深度超过Java虚拟机所容许的栈深度时,会发生栈溢出异常;
OutOFMemoryError:当虚拟机栈在动态扩展过程当中没有申请到足够的内存时,会发生内存溢出异常;
四、Java堆
1)堆内存是Java虚拟机所管理的内存中最大的一块;
2)线程共享,在虚拟机启动时建立;
3)用来存放对象实例和数组;
4)堆是垃圾收集器管理的主要区域,所以也称GC堆;
5)堆内存可扩展,可经过参数--Xmx和--Xms来设置最大堆内存和最小堆内存来控制;
6)若是堆中没有足够的内存来分配实例,且堆没法扩展时就会抛出OutOfMemoryError异常
五、方法区
1)同堆内存同样,方法区也是线程共享的内存区域;
2)用来存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;
3)根据Java虚拟机规范,当方法区没法知足内存分配需求时就会抛出OutOfMemoryError异常
六、直接内存
这部份内存既不是Java虚拟机运行时数据区,也不是Java虚拟机规范中定义的内存区域,可是这部份内存也会被频繁使用,并且还有可能引发OutOfMemoryError异常。本机内存的分配不会受到Java虚拟机内存分配的影响,可是当虚拟机中各区域的内存之和大于本机内存的话,就会致使动态扩展时出现OutOfMemoryError异常
以上就是Java虚拟机中的内存模型及各内存在程序运行过程当中所扮演的角色或所起的做用。下节将会总结各个内存区域出现内存溢出异常的缘由和解决方法。
备注:以上内容来源于《深刻理解Java虚拟机》,根据本身的理解来总结,有些内容和书本内容相同是由于只有这么描述才比较好懂,毕竟大神仍是大神,是颜色不同的烟火!!