转载出处:(http://blog.csdn.net/zhangerqing)程序员
Java虚拟机会将内存分为几个不一样的管理区,这些区域各自有各自的用途,根据不一样的特色,承担不一样的任务以及在垃圾回收时运用不一样的算法。整体分为下面几个部分:算法
程序计数器(Program Counter Register)、JVM虚拟机栈(JVM Stacks)、本地方法栈(Native Method Stacks)、堆(Heap)、方法区(Method Area)数组
一、程序计数器(Program Counter Register)多线程
这是一块比较小的内存,不在Ram上,而是直接划分在CPU上的,程序员没法直接操做它,它的做用是:JVM在解释字节码文件(.class)时,存储当前线程所执行的字节码的行号,只是一种概念模型,各类JVM所采用的方式不一样,字节码解释器工做时,就是经过改变程序计数器的值来选取下一条要执行的指令,分支、循环、跳转、等基础功能都是依赖此技术区完成的。还有一种状况,就是咱们常说的Java多线程方面的,多线程就是经过现程轮流切换而达到的,同一时刻,一个内核只能执行一个指令,因此,对于每个程序来讲,必须有一个计数器来记录程序的执行进度,这样,当现程恢复执行的时候,才能从正确的地方开始,因此,每一个线程都必须有一个独立的程序计数器,这类计数器为线程私有的内存。若是一个线程正在执行一个Java方法,则计数器记录的是字节码的指令的地址,若是执行的一个Native方法,则计数器的记录为空,此内存区是惟一一个在Java规范中没有任何OutOfMemoryError状况的区域。函数
二、JVM虚拟机栈(JVM Stacks)性能
JVM虚拟机栈就是咱们常说的堆栈的栈(咱们经常把内存粗略分为堆和栈),和程序计数器同样,也是线程私有的,生命周期和线程同样,每一个方法被执行的时候会产生一个栈帧,用于存储局部变量表、动态连接、操做数、方法出口等信息。方法的执行过程就是栈帧在JVM中出栈和入栈的过程。局部变量表中存放的是各类基本数据类型,如boolean、byte、char、等8种,及引用类型(存放的是指向各个对象的内存地址),所以,它有一个特色:内存空间能够在编译期间就肯定,运行期不在改变。这个内存区域会有两种可能的Java异常:StackOverFlowError和OutOfMemoryError。优化
三、本地方法栈(Native Method Stacks)操作系统
从名字便可看出,本地方法栈就是用来处理Java中的本地方法的,Java类的祖先类Object中有众多Native方法,如hashCode()、wait()等,他们的执行不少时候是借助于操做系统,可是JVM须要对他们作一些规范,来处理他们的执行过程。此区域,能够有不一样的实现方法,向咱们经常使用的Sun的JVM就是本地方法栈和JVM虚拟机栈是同一个。.net
四、堆(Heap)线程
堆内存是内存中最重要的一块,也是最有必要进行深究的一部分。由于Java性能的优化,主要就是针对这部份内存的。全部的对象实例及数组都是在堆上面分配的(随着JIT技术的逐渐成熟,这句话视乎有些绝对,不过至少目前还基本是这样的),可经过-Xmx和-Xms来控制堆的大小。JIT技术的发展产生了新的技术,如栈上分配和标量替换,也许在不久的几年里,即时编译会诞生及成熟,那个时候,“全部的对象实例及数组都是在堆上面分配的”这句话就应该稍微改改了。堆内存是垃圾回收的主要区域,因此在下文垃圾回收板块会重点介绍,此处只作概念方面的解释。在32位系统上最大为2G,64位系统上无限制。可经过-Xms和-Xmx控制,-Xms为JVM启动时申请的最小Heap内存,-Xmx为JVM可申请的最大Heap内存。
五、方法区(Method Area)
方法区是全部线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量等数据,通常来讲,方法区属于持久代(关于持久代,会在GC部分详细介绍,除了持久代,还有新生代和旧生代),也难怪Java规范将方法区描述为堆的一个逻辑部分,可是它不是堆。方法区的垃圾回收比较棘手,就算是Sun的HotSpot VM在这方面也没有作得多么完美。此处引入方法区中一个重要的概念:运行时常量池。主要用于存放在编译过程当中产生的字面量(字面量简单理解就是常量)和引用。通常状况,常量的内存分配在编译期间就能肯定,但不必定全是,有一些可能就是运行时也可将常量放入常量池中,如String类中有个Native方法intern()<关于intern()的详细说明,请看另外一篇文章:http://blog.csdn.net/zhangerqing/article/details/8093919>
此处补充一个在JVM内存管理以外的一个内存区:直接内存。在JDK1.4中新加入类NIO类,引入了一种基于通道与缓冲区的I/O方式,它可使用Native函数库直接分配堆外内存,即咱们所说的直接内存,这样在某些场景中会提升程序的性能。