jvm内存简单模型
程序员文章站
2022-05-24 11:39:24
...
先看一下jvm运行时的内存结构图:
直接内存:
直接内存并不是jvm运行时数据区的一部分,所建议它不受jvm内存总大小的限制。个人理解直接内存就是物理机可用的内存空间。
程序计数器:
程序计数器是每一个线程所独有的一个很小的内存区域,并不是多线程所共享的共享区域。它可以被看成是字节码指令执行的指针,线程的分支,循环,跳转,异常处理,线程恢复等功能都要依赖这个计数器来完成。如果当前线程正在执行的是一个java方法,那么程序计数器指向这个字节码指令的地址,如果当前执行的是一个本地方法,则程序计数器的指向为空。
java虚拟机栈:
与程序计数器一样,java虚拟机栈也是线程私有的,声生命周期与线程相同。每一个方法在执行时都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等。(更详细信息参考:http://smallbug-vip.iteye.com/blog/2275469)
本地方法栈:
本地方法栈为使用到的Native方法服务。
java堆:
java堆是被所有线程所共享的一块内存区域。大致可以认为所有的对象实例及数组都要在堆上分配。但是随着JIT编译器的发展与逃逸分析技术的逐渐成熟,对象实例及数组在堆上分配也不是那么绝对了。java堆是GC处理的主要区域,可以通过-Xmx -Xms两个参数来修改堆内存的大小。
方法区:
方法区与Java堆一样,也是一个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有另一个别名,叫非堆(Non-Heap).
对于习惯在Hotspot虚拟机上做开发的开发者来说,方法区也被称之为"永久区",本质上,两者并不等价,仅仅是因为Hotspot虚拟机设计团队选择把GC分代收集扩展到方法区,或者说使用永久代来实现方法区的而已。
根据虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
运行时常量池在jdk1.6之前也是方法区中的一部分。用于存放编译期间生成的各种字面量和符号引用,但是jdk1.7之后常量池被转移到了堆上。jdk1.8之后永久代消失,类的元数据信息相关的数据被移到了一个与堆不相连的本地内存区域。(详情参考:http://www.infoq.com/cn/articles/Java-PERMGEN-Removed)
运行时常量池:
jdk1.6之前运行时常量池是方法区的一部分,jdk1.7之后被转移到了堆内存中。它用于存放编译期生成的各种字面量的符号引用,比如String就存放在此。
直接内存:
直接内存并不是jvm运行时数据区的一部分,所建议它不受jvm内存总大小的限制。个人理解直接内存就是物理机可用的内存空间。
程序计数器:
程序计数器是每一个线程所独有的一个很小的内存区域,并不是多线程所共享的共享区域。它可以被看成是字节码指令执行的指针,线程的分支,循环,跳转,异常处理,线程恢复等功能都要依赖这个计数器来完成。如果当前线程正在执行的是一个java方法,那么程序计数器指向这个字节码指令的地址,如果当前执行的是一个本地方法,则程序计数器的指向为空。
java虚拟机栈:
与程序计数器一样,java虚拟机栈也是线程私有的,声生命周期与线程相同。每一个方法在执行时都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等。(更详细信息参考:http://smallbug-vip.iteye.com/blog/2275469)
本地方法栈:
本地方法栈为使用到的Native方法服务。
java堆:
java堆是被所有线程所共享的一块内存区域。大致可以认为所有的对象实例及数组都要在堆上分配。但是随着JIT编译器的发展与逃逸分析技术的逐渐成熟,对象实例及数组在堆上分配也不是那么绝对了。java堆是GC处理的主要区域,可以通过-Xmx -Xms两个参数来修改堆内存的大小。
方法区:
方法区与Java堆一样,也是一个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有另一个别名,叫非堆(Non-Heap).
对于习惯在Hotspot虚拟机上做开发的开发者来说,方法区也被称之为"永久区",本质上,两者并不等价,仅仅是因为Hotspot虚拟机设计团队选择把GC分代收集扩展到方法区,或者说使用永久代来实现方法区的而已。
根据虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
运行时常量池在jdk1.6之前也是方法区中的一部分。用于存放编译期间生成的各种字面量和符号引用,但是jdk1.7之后常量池被转移到了堆上。jdk1.8之后永久代消失,类的元数据信息相关的数据被移到了一个与堆不相连的本地内存区域。(详情参考:http://www.infoq.com/cn/articles/Java-PERMGEN-Removed)
运行时常量池:
jdk1.6之前运行时常量池是方法区的一部分,jdk1.7之后被转移到了堆内存中。它用于存放编译期生成的各种字面量的符号引用,比如String就存放在此。