Java内存区域
文章目录
内存区域
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙;
这就是Java和C++的一个最大区别,在Java中,不需要为每一个new操作去写配对的free代码,这些都由Java虚拟机去完成,正因为这样,我们得更好的理解Java虚拟机内存工作状态,以免出问题得时候能够自己去解决!
运行时数据区
下面提供一张Java虚拟机运行时数据区域划分图:(Java虚拟机在执行Java程序时会把它所管理的内存划分为若干个区域)
1.程序计数器(线程私有)
- 程序计数器是一块比较小的内存;
- 用途:可以看作是当前线程所执行的字节码的行号指示器;
- 每个线程都需要有一个独立的程序计数器,各条线程间的程序计数器互不影响,独立存贮,称这类内存为“线程私有”内存;
2.Java虚拟机栈(线程私有)
- 线程私有区域,生命周期和线程相同
- 用途:描述Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
- 局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的在方法运行期间不会改变局部变量表的大小;
- 这个区域规定了两种异常状况:
- StackOverflowError异常:线程申请的栈深度大于虚拟机所允许的深度;
- OutOfMemoryError异常:虚拟机栈动态扩展时无法申请到足够的内存;
3.本地方法栈(线程私有)
- 本地方法栈和Java虚拟机栈非常相似;
- 本地方法栈为虚拟机使用到的Native方法服务,虚拟机栈为虚拟机执行Java方法服务;
4.Java堆(所有线程共享的一块内存区域)
- Java堆基本是Java虚拟机所管理内存中最大的一块;
- Java堆的唯一目的:存放对象实例,几乎所有的对象实例都在这里分配内存;
- Java堆是垃圾收集器管理的主要区域;
- Java堆还可细分:新生代、老年代;
- Java堆可以处于物理上不连续的内存空间中;
- 这个区域规定了一个异常状况:
- OutOfMemoryError异常:在堆中已经没有内存完成实例分配,并且堆也无法完成扩展时,将会抛出此异常
5.方法区(所有线程共享的一块内存区域)
- 目的:用于存储已被虚拟机加载的类信息、常量、静态变量、即编译器编译后的代码等数据;
- 方法区可以选择不实现垃圾收集,这个区域的回收条件比较苛刻,但还是必须的,有些bug就是因为对方法区的回收没有做好;
- 这个区域规定了一个异常状况:
- OutOfMemoryError异常:当方法区无法满足内存分配需求 ;
5.1运行时常量池
- 运行时常量池是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外、还有一项信息是常量池;
- 作用:用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放
6.直接内存
- 直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域;
- 可能产生OutOfMemoryError异常 ;