JAVA内存模型

概述

JAVA虚拟机在运行的java程序的过程中,会把所管理的内存分为几个不同的区域,每个区域都有各自的用途,创建时间跟销毁时间,按照java虚拟机的规范,分为以下几个区域:

程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池(属于方法区)、直接内存

1、程序计数器

一块相对比较小的内存空间,属于线程私有,可以当做是当前线程所执行字节码的指示灯,字节码解释器通过这个来获取下一条需要执行的字节码命令。一个处理器在确定的某一个时刻,只会执行一条线程,多条线程之间来回切换,每条线程切换之后需要知道之前执行到哪,所以每条线程都需要有一个自己的程序计数器,各个线程之间的程序计数器互不影响。

如果,线程执行的是一个JAVA方法的时候,程序计数器存储着是正在执行的字节码命令的地址;如果线程执行的是一个本地方法的时候,程序计数器为空。

2、java虚拟机栈

线程私有,生命周期跟线程一样长,随着线程的创建而创建,随着线程的销毁而销毁。描述的是一个java方法执行的内存模型,一个java方法执行的时候,会创建一个栈栈,里面存储着局部变量表、操作数帧、方法出口等信息。每一个方法从调用到执行结束,都对应着在java虚拟机栈中的入栈跟出栈的过程。
局部变量表存放了在编译期间可知的各种基本数据类型以及对象的引用。其所需的内存空间在编译期间可以确定,在方法运行期间不会改变其大小。

3、本地方法栈

与java虚拟机栈相似,只不过存放的不是java方法而是本地方法,对本地方法栈中方法是用的语言、使用方式和数据结构并没有强制规定。

4、Java堆

是java内存中最大的一块,是被所有线程共享的一块内存区域。所有的对象实例都是在这里被创建的。但是,随着JIT编译器的发展和逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术会导致一些奇妙的变化,所以所有对象都是在堆上创建就变得不是那么绝对。

这一块是java垃圾收集器主要管理的区域,常常被称之为“GC堆”

5、方法区

同堆一样,是所有线程共享的内存区域,用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。在JDK7这个版本之前,绝大多数人把这块内存区域称之为“永久代”(Permanent Generation),HotSpot虚拟机的设计团队把GC分代手机拓展到方法区,这样,HotSpot的垃圾收集器可以像管理堆内存一样,管理这块内存区域,可以省去专门为方法区编写内存管理代码的工作。这个有一个不好的地方,就是很容易遇到内存溢出的问题(永久代有-XX:MaxPermSize的上限)。在JDK8出现以后,已经完全废除了永久代空间,采用元空间取代,即采用直接内存来存储类的元数据信息,只要计算机的内存足够,就不会发生内存溢出的问题。

6、运行时常量池

这部分空间属于方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息之外,还有一项信息是常量池,用于存放编译器生成的各种字面量和符号的引用。除了保存class文件中描述的符号引用外,还会把翻译出来的直接引用也放到常量池中。

7、直接内存

并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。在JDK1.4中加入了NIO(New Input/Output),引入了一种基于通道和缓存区的I/O方式,可以使用Native函数直接分配堆外的内存,然后通过存储在堆中的DirectByteBuffer对象作为这块内存的引用进行操作。在某些场景中能显著提高性能,避免了在Java堆和native堆中来回地复制数据。受主机内存影响。


以上内存操作《深入理解Java虚拟机》


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值