java虚拟机总共分成。
线程共享:方法区,堆,执行引擎,本地库接口
非线程共享:虚拟机栈,本地方法栈,程序计数器。
这上述几大类。在线程共享和非共享之外。运行时的数据区包含:方法区,堆,虚拟机栈,本地方法栈,程序计数器这几类。借用《深入理解java虚拟机》这本书中的图来描述一下如下:
下面结合书中的解释以及自己的理解重新看下虚拟机中这几大块的作用。
1.程序计数器
程序计数器十一块较小得看内存空间,它是当前线程所执行的字节码的行号指示器,程序的分支,循环,跳转,异常处理等功能都依赖这个计数器。由此可以看出,程序计数器是针对独立的线程服务的,好比这个线程的执行进度,为了保证线程执行进度的正确性,所以要保证每个线程都拥有自己的程序计数器。也就是线程私有的。本地方法的计数器为空,且不会出现OutOfMemoryError 情况的区域。
2.java虚拟机栈
java虚拟机栈广义上来说就是所谓的栈内存。大多数情况下是指局部变量表。局部变量表主要用于存放编译器可知的基础数据类型(boolean,byte,char,shor, int, float ,double,long),对对象引用,和returnAddress类型。这些数据在局部变量表中用slot标书。long和double是2个slot–64位。在编译器就会完全确定这些局部变量的大小,不会再运行期改变。具体大小由具体的虚拟机决定。此块也是线程独占的。
本地方法栈
本地方法栈也是java栈的一部分,不过此块内存是为了本地方法服务。
java堆
堆就是java主要内存区域,也是内存中最大的一块。java里几乎所有的对象都在此块内存分配大小。java的垃圾回收管理器管理的内存区域。Java 堆既可以被实现成固定大小的,也可以是可扩展的,不过当前主流的 Java 虚拟机都是按照可扩展来实现的(通过参数-Xmx 和-Xms 设定)。
方法区
方法区用于存储已经被加载的类型信息,常亮,静态变量,即时编译器编译后的代码缓存数据。
jdk8以前这部分被称为永久代,比如静态变量会一直存在在内存中,这样很容易造成内存溢出。
jdk7时hotspot把字符串常量池和静态变量移出方法区。到了jdk8完全废弃。改用本地内存中的源空间。
运行时常量池
运行时常量池(Runtime Constant Pool)是方法区的一部分。Class 文件中除了有类
的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool
Table),用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放
到方法区的运行时常量池中。
直接内存
在nio中引入了通道channel和缓冲区buffer的i/o方式。可以直接分配堆外的内存通过堆内的DirectByteBuffer对象作为这块的引用进行操作。
不管堆还是直接内存都受到物理机器的直接限制。
JVM内存区域分析
最新推荐文章于 2024-11-12 21:36:56 发布