深入理解java虚拟机之--数据区域

java内存区域和jvm运行时数据区域,上图


1.1 程序计数器

如上图程序计数器是线程私有的,他是一块较小的内存空间,是当前线程执行的字节码的行号指示器。通过改变计数器的值来选取下一条需要执行的字节码指令。

在多线程环境中,同一时间内,一个处理器都只会处理一个线程,为了线程切换后能恢复到正确的执行位置,每条线程都要有一个独立的程序计数器,各线程间不相互影响,独立存储,我们称这类内存区域为线程私有的内存。

在执行native方法时,程序计数器为空。而且程序计数器生成的内存区域是唯一一个不会出现OutOfMemoryError的区域。

1.2 Java虚拟机栈----stack栈

Java虚拟机也是线程私有的,它的生命周期与线程相同。每个程序在执行的时候都会创建一个栈,用于存储局部变量表、操作数栈、动态链接、方法出口等。每个方法从调用到执行完成的过程,就对应着一个栈在虚拟机中入栈到出栈的过程。

其中局部变量表包含:基本数据类型(int double char等)、对象的引用(指向对象在堆中位置的引用指针)和returnAddress类型(指向一条字节码指令的地址)。

在java虚拟机规范中,对这个内存区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出StackOverflowError异常;此时引发虚拟机栈的动态的扩展,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。

1.3 本地方法栈

本地方法栈与虚拟机栈所发挥的作用非常相似,其区别是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则为虚拟机使用到的native方法服务。和虚拟机栈一样,本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。

HotSpot虚拟机中把本地方法栈和虚拟机栈合二为一

1.4 Java堆

对于大多数应用来说,java堆(Java Heap)是java虚拟机所管理的内存中最大的一块。java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。堆内存的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。java虚拟机规范中规定:所有对象和数组都要在堆上分配。

java堆是垃圾收集器管理的主要区域。从内存回收的角度,现在的收集器大部分采用分代收集算法,所以java堆还可以分为:年轻代和老年代;年轻代还可以分为Eden区、From Survivor和To Survivor空间。

根据Java虚拟机规范:java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的。当前主流的虚拟机java堆的大小都是可以扩展的(通过-Xmx和-Xms控制)。如果内存中没有足够的内存完成对象的实例化,并且堆无法继续扩展的情况下会抛出OutOfMemoryError异常。

1.5 方法区

方法区(Method Area)与java堆一样,是各个线程共享的内存区域。用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

在HotSpot虚拟机中,方法区可以看作“永久代”,因为Hotshot团队把GC分代收集扩展到方法区。

1.6 运行时的常量池

运行时的常量池是方法区的一部分,方法区除了加载类的版本、字段、方法等描述信息外,还有一项就是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。

1.7 直接内存


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页