十一期间很简单的介绍了一下java虚拟机的基本内容,没有很详细的介绍,想了解以前内容的,能够看看从公众号历史信息自行查找下,今天本身又回来写了一篇,有什么问题欢迎纠正。java
运行时数据区主要有程序计数器,Java虚拟机栈,本地方法栈,Java堆,方法区,运行时常量池等部分组成。
数组
针对上面的图文,下面开始开始进入各个部分的详细内容了。微信
程序计数器,线程私有,因为Java虚拟机的多线程是经过线程流转切换并分配处理器执行时间的方式来实现的,在任意一个肯定的时间点,一个处理器都只会执行一条线程中的指令。所以,为了线程切换后能恢复到正确的执行位置,每条线程都须要有一个独立的程序计数器,即程序计数器是线程私有的。若是线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;若线程正在执行的是Native方法,这个计数器的值通常就是undefined。多线程
程序计数器可能出现的异常:此内存区域是惟一一个在Java虚拟机规范中没有规定任何OutofMemory区域的地方,通常遇到OOM问题,不会是这里。函数
Java虚拟机栈,一样是线程私有的,Java虚拟机栈描述的是Java方法执行的,每一个方法在执行的同时都会建立一个栈帧用于存储局部变量表,操做数栈,动态连接,方法出口等信息。每个方法从调用直至完成的过程,就对应着一个栈帧在虚拟机栈中入栈和出栈的过程。
性能
局部变量表存放了编译期可知的各类数据类型,对象引用和返回地址类型,而且它所须要的内存空间在编译期完成分配,在方法运行期间不会改变局部变量表的大小。
spa
ok,咱们继续吧,下面要说的就是最最最最重要的了,Java堆,Java堆属于线程共享的区域,全部的对象实例和数组都要在堆上进行分配,Java堆在虚拟机启动时建立,此内存的惟一目的就是存放对象实例,Java堆能够处于物理上不连续的内存空间,只要逻辑上是连续的便可。.net
在这块区域内,可能出现的异常,当在堆中没有内存能够完成实例对象的分配时,堆也没法再扩展时,会出现OutOfMemoryError错误信息。线程
下面说下方法区吧,方法区也是线程共享的,方法区用于存储虚拟机加载的类信息,常量,静态变量,及时编译器JIT编译后的代码等数据,这块区域的内存回收目标主要是针对常量池的回收和对类型的卸载。可能出现的异常,当方法区没法知足内存分配需求时,也一样会出现OutOfMemroyError错误信息。翻译
运行时常量池是方法区的一部分。Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项就是常量池,用于存放编译期生成的各类字面量和符号引用,这部份内容将在类加载后进入方法区的运行时常量池中存放。通常来讲,除了保存Class文件中的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。运行时常量池相对于Class文件常量池的另一个重要特征是具有动态性,即运行期间也可能将新的常量放入池中,String类的itern()方法,此区域可能出现的异常,当常量池没法再申请到内存时会跑出OutOfMemoryError错误。
因为直接内存不属于Java虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,JDK1.4中新加入了NIO类,引入了一种基于通道与缓冲区的I/O方式,它可使用Native函数库直接分配对外内存,而后经过一个存储在Java堆中的DirectByteBuffer对象做为这块内存的引用进行操做,避免了在Java堆和Native中来回复制数据,在一些场景中显著提升性能。
直接内存的分配不会受到Java堆大小的限制,可是,既然是内存,确定会受到本机总内存大小和处理器寻址空间的限制。
在这说明一下,以上说的内容会有一点和jdk8不太同样,由于jdk8多了元空间的概念,本身没有在这里进行说下,说的虚拟机针对于主流的虚拟机hotSpot,ok接着十一那篇文章,这篇文章也详细介绍了每一个区域都是干啥的,都会出现什么异常,时间也不早了,写一篇文章,从构思到书写,花费的时间确实很长,感谢你的阅读,喜欢这篇文章的能够分享一下,喜欢的能够关注一下,ok,这篇文章就到这结束了。来源java相关书籍。
本文分享自微信公众号 - WwpwW(gh_245290c1861a)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。