http://my.oschina.net/u/567296/blog/303780 java
JVM的内部结构以下图:程序员
JVM主要包括两个子系统和两个组件:编程
1. 两个子系统分别是Class loader子系统和Execution engine(执行引擎) 子系统;服务器
1.1 Class loader子系统的做用:根据给定的全限定名类名(如 java.lang.Object)来装载class文件的内容到 Runtime data area中的method area(方法区域)。Java程序员能够extends java.lang.ClassLoader类来写本身的Class loader。编程语言
1.2 Execution engine子系统的做用:执行classes中的指令。任何JVM specification实现(JDK)的核心都是Execution engine,不一样的JDK例如Sun 的JDK 和IBM的JDK好坏主要就取决于他们各自实现的Execution engine的好坏。spa
2. 两个组件分别是Runtime data area (运行时数据区域)组件和Native interface(本地接口)组件。操作系统
2.1 Native interface组件:与native libraries交互,是其它编程语言交互的接口。当调用native方法的时候,就进入了一个全新的而且再也不受虚拟机限制的世界,因此也很容易出现JVM没法控制的native heap OutOfMemory。.net
2.2 Runtime Data Area组件:这就是咱们常说的JVM的内存了。它主要分为五个部分——线程
一、Heap (堆):一个Java虚拟实例中只存在一个堆空间,Java堆是被全部线程共享的,在虚拟机启动时建立。Java堆的惟一目的就是存放对象实例,绝大部分的对象实例都在这里分配。Java堆内还有更细致的划分:新生代、老年代,再细致一点的:eden、from survivor、to survivor,甚至更细粒度的本地线程分配缓冲(TLAB)等,不管对Java堆如何划分,目的都是为了更好的回收内存,或者更快的分配内存。指针
Java堆能够处于物理上不连续的内存空间,它逻辑上是连续的便可,就像咱们的磁盘空间同样。实现时能够选择实现成固定大小的,也能够是可扩展的,不过当前全部商业的虚拟机都是按照可扩展来实现的(经过-Xmx和-Xms控制)。若是在堆中没法分配内存,而且堆也没法再扩展时,将会抛出OutOfMemoryError异常。
二、Method Area(方法区域):被装载的class的信息存储在Method area的内存中。当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,而后读入这个class文件内容并把它传输到虚拟机中。叫“方法区”可能认识它的人还不太多,若是叫永久代(Permanent Generation)它的粉丝也许就多了。它还有个别名叫 作Non-Heap(非堆)。
方法区中存放了每一个Class的结构信息,包括常量池、字段描述、方法描述等等。Class文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量表(constant_pool table),用于存放编译期已可知的常量,这部份内容将在类加载后进入方法区(永久代)存放。可是Java语言并不要求常量必定只有编译期预置入Class的常量表的内容才能进入方法区常量池,运行期间也可将新内容放入常量池(最典型的String.intern()方法)。
运行时常量池是方法区的一部分,天然受到方法区内存的限制,当常量池没法在申请到内存时会抛出OutOfMemoryError异常。
三、Java Stack(java的栈):虚拟机只会直接对Java stack执行两种操做:以帧为单位的压栈或出栈。栈描述的是Java方法调用的内存模型:每一个方法被执行的时候,都会同时建立一个帧(Frame)用于存储本地变量表、操做栈、动态连接、方法出入口等信息。每个方法的调用至完成,就意味着一个帧在VM栈中的入栈至出栈的过程。
四、Program Counter(程序计数器):每个线程都有它本身的PC寄存器,也是该线程启动时建立的。PC寄存器的内容老是指向下一条将被执行指令的饿地址,这里的地址能够是一个本地指针,也能够是在方法区中相对应于该方法起始指令的偏移量。
五、Native method stack(本地方法栈):保存native方法进入区域的地址.
以上五部分只有Heap 和Method Area是被全部线程的共享使用的;而Java stack, Program counter 和Native method stack是以线程为粒度的,每一个线程独自拥有本身的部分。
此外还有本机直接内存的管理(Direct Memory) -- 直接内存并非虚拟机运行时数据区的一部分,它根本就是本机内存而不是VM直接管理的区域。
显然本机直接内存的分配不会受到Java堆大小的限制,可是即然是内存那确定仍是要受到本机物理内存(包括SWAP区或者Windows虚拟内存)的限制的,通常服务器管理员配置JVM参数时,会根据实际内存设置-Xmx等参数信息,但常常忽略掉直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操做系统级的限制),而致使动态扩展时出现OutOfMemoryError异常。
JVM内存模型实例以及参数对应: