深入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堆中来回复制数据。
之前一直学习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堆中来回复制数据。
相关文章推荐
- Java 6 JVM参数选项大全(中文版)
- 深入解析JVM对dll文件和对类的装载过程
- Java虚拟机JVM性能优化(二):编译器
- Java程序员必须知道的5个JVM命令行标志
- 解决Java中OutOfMemoryError的问题
- Java虚拟机JVM性能优化(三):垃圾收集详解
- 解析Java虚拟机中类的初始化及加载器的父委托机制
- JAVA中JVM的重排序详细介绍
- 浅谈Java的虚拟机结构以及虚拟机内存的优化
- Java虚拟机JVM性能优化(一):JVM知识总结
- Android Studio 报错failed to create jvm error code -4的解决方法
- 解析Linux系统中JVM内存2GB上限的详解
- 了解Java虚拟机JVM的基本结构及JVM的内存溢出方式
- Java堆空间占满的gc日志实例
- java动态代理模式
- Groovy Meta Object Protocol
- xms/xmx/xss在kette中的调优设置
- JVM工作原理和特点
- JVM性能调优监控工具jps、jstack、jstat、jmap、jinfo使用详解
- jmap详解