《深入理解Java虚拟机》学习笔记--JVM运行时数据区

来源:互联网 发布:工程设计图软件 编辑:程序博客网 时间:2024/06/05 01:59

许多大牛们都写过关于JVM相关的文章,我只是一个初来乍到的小白。写这篇文章主要是用来巩固一下学过的知识,其中有一些自己的看法。有些地方说的可能不对,请大家多多指教。

我在学习Java之前学过c跟c++,当然就是在大学课堂上学的那点知识,根本没有过深入了解。对于使用c++开发的程序员来说,他们对于内存还是比较敏感的。因为他们能手动在内存上开辟空间,而且使用完后要手动释放。在给一个类写构造函数的时候,一定要写上析构函数来释放占用的内存。而这些问题对于Java程序员来说都是不存在的。因为Java虚拟机实现了自动的垃圾回收机制。对于一些刚开始学习Java语言的同学来说,对于虚拟机的内存只是知道有栈区和堆区,栈里面方的就是一些对象的引用,局部变量什么的;堆区里放的都是new出来的对象实例。有些同学还知道一些静态变量、字符串常量都会放到方法区。其实这已经大概的描述出了大概的内存模型。如下图,左边的方法区和堆区是所有线程共享的区域,右边的虚拟机栈、本地方法栈和程序计数器是线程独有的,也就是说,每个线程里都会有这三个区域。

   

首先说程序计数器:它占用内存中的一小部分空间。如果学过计算机组成原理的同学应该很清楚它的作用,就是记录下一条字节码指令执行的地址。说白了,就是记录你的java程序执行到哪一行了。比如说,在多线程环境下,Thread1正在执行,由于某种原因被阻塞了,等到Thread1能够继续执行的时候,程序计数器会告诉你从哪一行代码接着执行。这就是为什么程序计数器是线程独有的。

虚拟机栈:大家经常说的栈区,其实说的就是虚拟机栈,它是描述Java方法执行的内存模型。什么意思呢,每个方法在执行的时候会创建一个栈帧,Java虚拟机栈是用来存放栈帧的。每一个Java方法从开始调用到执行结束,就对应着一个栈帧在Java虚拟机栈中的一次入栈和出栈的过程。那么,这个栈帧到底是个什么东西呢?大家知道栈区放的是局部变量和对象的引用,这些东西都是放在栈帧中的。栈帧中存放的是局部变量表、操作数栈、动态链接、方法的出口等信息。那些局部变量和对象的引用都放在了栈帧中的局部变量表中。当一个方法被调用的时候,先创建栈帧,把局部变量和对象引用放进去,然后栈帧被放入到虚拟机栈中执行,方法执行结束,栈帧出栈。大概流程就是这样的。

本地方法栈:作用和虚拟机栈非常相似,他们的区别就是,虚拟机栈执行的是Java方法,本地方法栈执行的是本地的Native方法。在我们常用的HotSpot虚拟机中是不区分虚拟机栈和本地方法栈的。

Java堆:这是内存中最大的一块,也是存放绝大多数实例对象的地方。它是所有线程共享的区域,所以在虚拟机启动的时候就被创建。Java有个与众不同的地方就是它的垃圾回收机制,Java堆是垃圾回收器管理的主要区域。大家也许听过内存中有新生代、老年代、永久代什么的。新生代和老年代就位于Java堆中,在接下来的文章中我会介绍。那么永久代呢?

方法区:用来存放虚拟机加载的类信息(在以后虚拟机类加载机制会说明)、静态变量和常量的数据。也是线程共享的区域。Java虚拟机规范中描述方法区是Java堆的一个逻辑部分,它有个别名,叫Non-Heap(非堆),用于和Java堆区分开。上面说的永久代,说的就是方法区。

大概说一下新生代、老年代和永久代都是什么意思吧,肯能有的同学现在会有疑问。每个“代”是根据对象生存时间长短来命名的。新生代就是生命周期比较短对象;老年代呢,就是活的会比较长;永久代就不用说了,几乎死不了。在接下来的关于GC的文章中会详细的介绍。

JVM运行时数据区大体上就是这个样子了,我现在只能理解到这里,有什么不妥的地方还请大家多多指教。

阅读全文
0 0