了解JVM的运作对于Java程序员来说是一个知根知底的过程,可以帮助程序员写出高效的代码,同时对自己代码的运转有个了解,本文我们简单地介绍下JVM的内存模型。
首先的,我们说说程序计数器,程序计数器的作用其实类似于传统处理器中的PC,是正在执行的字节码的行号指示器,通过改变自身的值,来控制需要选取哪一条字节码指令,从而做到分支、跳转、循环、异常处理等基础操作。为了保证每一次线程在获取CPU的时候程序计数器都能回到原来的位置,所以每一个线程都有一个独立的线程计数器,所以该内存空间为“线程私有”的。
再就是Java虚拟机栈,它是Java方法处理的内存模型,每一个Java方法被调用的时候都会创建一个栈帧,栈帧中存储着局部变量表、操作数栈、动态链接、方法出口等内容。其中,局部变量表中存储着可预知的基础数据类型、对象引用、返回地址(指向一条字节码指令的地址),而一次方法的执行到返回,就意味着一次入栈和出栈,很显然,这部分的内存也是“线程私有”的。
本地方法栈,大体上和Java栈相同,但是是服务于本地方法(Native)的。
以上三种内存空间都是“线程私有”的,以下我们来讲述一些“线程公有”的内存模型,也就是意味着他们随着虚拟机的启动而创建,随着虚拟机的关闭而消亡。
Java堆,几乎所有的对象实例和数组都是在该区域创建的,是JVM管理的最大的一块区域,也是GC活动的核心场所。
方法区,当JVM使用类装载器装载一个类的时候,JVM会先找到指定的字节码文件,再读入该字节码文件,最后将其信息加在导方法区内存中,最后返回一个class实例。很显然,该内存主要用于存放类的信息,如类名、类修饰符等,其中方法区中有一片区域,叫做运行时常量池。运行时常量池用于存放字段、方法信息、静态变量。
上诉五种都是为JVM所管理的内存区域,我们再介绍一种比较特殊的内存区域,直接内存,他是并不是JVM内存模型的划分范围,他的作用是什么呢?
在JDK1.4之后,Java引入了NIO,一种基于通道和缓冲区的IO方式,使用native函数库直接分配堆外内存,如此就无需在Java堆上新建对象作为中间区域调用IO了。直接内存的读写效率是高于堆内存的,直接内存的申请耗费更高的性能。