您的位置:首页 > 其它

深入jvm-----------之基本存储,导致OutOfMemoryError

2016-03-19 00:00 274 查看
摘要: java运行时数据区:方法区(Method Area)、虚拟机栈(VM Stack)、本地方法栈(Native Method Stack)、堆(Heap)、程序计数器(Program Counter Register)

之前一直学习jvm,也只是在网上搜了搜,没有系统的学习一下,这次系统学习一下,记录一些关键的东西,大家共同学习,有什么好的建议提出来。

java运行时数据区:方法区(Method Area)、虚拟机栈(VM Stack)、本地方法栈(Native Method Stack)、堆(Heap)、程序计数器(Program Counter Register)。

程序计数器(Program Counter Register):

是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器。主要用来选取下一条执行什么样的字节码指令,说白了就是靠他来确定下一行要执行什么语句。

在任一时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。所以为了在线程之间互相切换后还能够恢复到原来的状态,每一个线程都有一个独立的程序计数器,互不影响,独立存储,称为“线程私有”。特例:如果正在执行java方法,则计数器记录的是正在执行的虚拟机字节码指令地址;如果执行的是Native方法,则这个计数器为空。

虚拟机栈:

就是常说的java内存栈,和计数器一样也是线程私有的,生命周期与线程相同。存放编译器可知的基本数据类型、对象引用(不同于对象本身,可能是一个指向对象起始地址的引用指针)和returnAddress类型(指向了一条字节码指令的地址).虚拟机栈jvm规定了两种异常:1、当线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflow异常。2、一般jvm都可动态扩展,但是如果扩展到无法申请到足够内存,就会抛出OutOfMemoryError异常。

本地方法栈:

和虚拟机栈基本一样,虚拟机栈是为jvm方法字节码服务,本地方法栈是为虚拟机使用到的native方法服务。Sun HotSpot直接把二者合一了。抛出异常同虚拟机栈

java堆:

是jvm管理内存中最大的一块。是被所有内存共享的一块内存。jvm启动时创建。此内存唯一目的就是存放对象实例,几乎所有对象实例以及数组都要在堆上分配。但是随着JIT编译技术的发展与逃逸技术逐渐熟悉,栈上分配、标量替换优化技术会导致一些微妙的变化,对象都在堆上分配也不那么绝对了(这个可以自己搜搜)。

同样java堆是垃圾搜集器主要管理的区域。有时又叫“GC堆(Garbage Collected Heap)”。java堆可以通过-Xmx和-Xms修改。如果堆中没有内存完成实例分配,且堆也无法再扩展会抛出OutOfMemoryError异常。

方法区:

是各个线程共享的内存区域,他用于存储已被jvm加载的类信息、常量、静态变量、即时编译后的代码等存储。虽然jvm把方法描述为堆一个逻辑部分,但是却有一个别名叫做Non-Heap(非堆),目的应该是区分域java堆的区别。

在HotSpot上,方法去也被称为“永久代”(Permanent Generation)。

运行时常量池:是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。

直接内存(Direct Memory):

不是jvm运行时数据区的一部分,也不是jvm规范中定义的内存区域。同样如果机器物理内存不足也会导致此处抛出OutOfmemoryError异常。例如:NIO类,引入基于通道与缓冲区的IO方式,他可以使用native函数库直接分配堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,可以显著提高性能,因为避免了java堆和native堆中来回复制数据。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息