Java虚拟机(一)--Java内存区域

java

Java GC(Garbage Collection,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该机制对JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop)的保证JVM中的内存空间,防止出现内存泄露和溢出问题。

我们将根据 《深入理解JAVA虚拟机》第二版的内容进行依次的讲解。

首先,我们需要直销的就是Java内存区域的相关知识。我们将介绍虚拟机内存的各个区域,区域的作用、服务对象和其中可能的问题。

一、运行时数据区域

Java虚拟机运行时内存划分主要如下图所示:

1)程序计数器

可以把程序计数器看作是当前线程所执行的字节码的行号指示器。最主要的作用是,Java虚拟机在执行多线程的时候,是通过轮流切换并分配处理器执行时间的方式来实现的,如果需要当切换到当前线程过后能够回到正确的位置上,就需要程序计数器来实现。

程序计数器是线程私有的 这点很容易理解,只有拥有它的线程能够改变它,不然上面所描述的过程会出现很大的问题。

如果线程执行的是一个Java方法,计数器记录正在执行的虚拟机字节码指令的地址,如果是Native方法,计数器值为空(Undefined)。

2)Java虚拟机栈

Java虚拟机栈是线程私有的。

Java虚拟机栈是描述Java方法执行的内存模型,每个方法在运行时都会有一个栈帧,具体的模型在后面讲Java字节码执行引擎的时候会详细讲解,在这里我们可以先给出一幅图:

其中包括的局部变量表,操作数栈,动态链接和返回地址,其中具体的功能和地址在后面详细讲解,这里给出相信会让这里的一些概念理解给予帮助。

每一个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

在这里给出局部变量表的部分功能和性质:局部变量表存放方法内部的局部变量,包括编译期的基本数据类型(boolean, byte, char, short, int, float, long, double),对象引用(一般是一个指向对象的引用指针)和returnAddress类型。其中long和double会占用两个局部变量空间(Slot),其余都占1个局部变量空间。具体的流程和相关知识讲解都放在讲解字节码执行引擎进行。

3)本地方法栈

本地方法栈和Java虚拟机栈非常相似,只不过执行的是本地方法

本地方法栈为线程私有

4)Java堆

首先,Java堆是线程共享的,几乎所有的对象实例都放在这里,进行分配内存

Java堆可以细分为两个代(Generation):新生代和老年代。根据GC算法的不同,早新生代和老年代中还可以接着细分。这一点后面讲垃圾回收的时候会讲解。

需要注意的是,Java堆在物理地址上是不连续的,但是在逻辑地址上是连续储存的。当然也有可能在物理地址上是连续储存的。主要根据GC算法的不同而不同。

5)方法区

和Java堆一样,方法区试线程共享的,用于储存虚拟机家在的类信息,常量,静态变量,即时编译器编译后的代码(就是储存字节码文件——.class文件)等数据。

很重要的一点是,对hotspot虚拟机上进行开发和部署的开发者来说,很多人愿意把方法区称为“永久代”。在《深入理解Java虚拟机》一书中提到,本质上两者并不等价,仅仅是因为hotspot虚拟机的设计团队把GC分代手机扩展至方法区,也就是说Full GC包括堆方法区进行的GC操作。

extra:

6)运行时常量池

其实单独列出运行时常量池不太合适,因为运行时常量池是方法区的一部分,用来储存class文件中的常量池(关于常量池的相关信息和分析会在讲解类文件时详细进行讲解)。

7)直接内存

直接内存其实不是Java虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是它仍然被频繁的使用

JDK1.4种新加入了NIO(new Input/Output)类,引入了一种基于通道(Channal)和缓冲区(Buffer)的I/O方式,使用Native函数库直接进行堆外内存的分配操作。通过一个DirectByteBuffer对象作为这块内存的引用进行操作。

以上是 Java虚拟机(一)--Java内存区域 的全部内容, 来源链接: utcz.com/z/394445.html

回到顶部