JVM内存结构
2013-09-09 15:39
176 查看
JVM包含两个子系统和两个组件。
子系统分别是ClassLoader和ExecutionEngine,两个组件是Runtime Data Area和Native Interface,其中,Runtime Data Area中就包含了我们常说的JVM内存。
Runtime Data Area又将内存分为不同的区域,用户存储不同的数据:
Method Area —— 方法区,被ClassLoader所装载的class文件以及相关的方法信息、域信息、静态变量等都存放在这个区域内。该区域是所有java线程共享。
当虚拟机装载某个类型时,它使用类装载器,定位对应的class文件,然后读入这个class文件内容并传输到虚拟机中,虚拟机会提取其中的类型信息,并将这些信息存储到方法区。该类型中的类(静态)变量同样也存储到方法区中。因为被所有线程共享,要考虑多线程访问的同步问题。
Heap —— 堆区,用来存放java对象和数组,通常所说的GC(垃圾回收器)就是针对该区域,一个java虚拟机实例只有一个堆,直接由java虚拟机进行管理,在虚拟机启动的时候创建,该区域被所有线程共享。堆可以动态的分配内存大小,存取速度比较慢。
每一个java程序独占一个jvm实例,每一个jvm实例只有一个堆空间,因此此java程序的所有线程共享这个堆。因此每个java程序都有自己独立的堆空间,不会彼此干扰。但是同一java程序的多个线程都共享着一个堆空间,就得考虑多线程访问对象(堆数据)的问题(还有,并发访问静态属性、单例等等,具体情况具体分析)。
Stack —— 栈区,用来存放JVM内存指令,每个线程都有自己的栈。优势是,存取速度比较快,栈里面的数据可以共享,但是内存中的数据大小和生存期必须是确定的,缺乏灵活性。
java程序以帧为单位保存线程的运行状态。虚拟机只会对java stack执行两种操作:以帧为单位的压栈或出栈。每当线程调用一个方法的时候,就对当前状态作为一个帧保存到java stack中(压栈),当调用一个方法返回时,从java stack中弹出一个栈(出栈)。栈的大小有一定的限制,可能会出现StackOverFlow的问题。
Program Counter Register ——程序计数器, 每一个线程都有自己的PC寄存器,是该线程启动时创建的。PC寄存器的内容总是指向下一条被执行的指令的地址。
Native Method Stack ——本地方法栈, 保存本地方法进入区域的地址。对于一个运行中的java程序而言,它还可能用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时,它就进入了一个全新的并且不受虚拟机控制的世界。本地方法可能通过本地方法接口来访问虚拟机的运行时数据区,还可以做任何它想做的事情。比如调用寄存器、在操作系统中分配内存等等。总之,本地方法具有和JVM相同的能力和权限。
通常,可以将JVM分为堆区和非堆区,堆为上面的Heap区域,剩下的都是非堆区域。GC主要针对的是堆区域。
垃圾分代回收算法
基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年轻代、年老代、持久代,对不同生命周期的对象使用不同的算法进行回收。
java的内存模型分为:
Young(年轻代)
Tenured(年老代)
Perm(永久代)
1、年轻代(JVM中heap的一部分)
年轻代分为三个区,一个Eden区,两个Survivor区。大部分对象在Eden区中生成,当Eden满了的时候,程序又需要创建新的对象,此时JVM的垃圾回收器将对Eden区域进行垃圾回收,将Eden区中不再被其它对象所引用的对象进行销毁工作。将还有其它对象引用的对象将被移动Survivor-0区(两个中的一个,Survivor区用于存放垃圾回收器回收时幸存下来的对象),当这个Survivor-0区满了的时候,进行垃圾回收销毁没有被其它引用对象引用的java对象,此区的存活的对象将被移动到另一个Survivor-1区,如果Survivor-1区有足够空间就放到Survivor-1区,如果Survivor-1也满了,JVM会对Survivor-1进行垃圾回收,销毁没有被其它引用对象引用的java对象,将幸存的java对象移动到养老区。
2、年老代(JVM中heap的一部分)
年老代存放的是从年轻代存活的对象。一般来说年老代存放的都是生命周期比较长的对象。
如果从Survivor-1移动到年老代的时候,年老代有足够空间则放到年老区,如果年老区没有足够空间,则JVM的垃圾回收期会对年老区进行垃圾回收,销毁没有被其它引用对象引用的java对象,并保留那些被其它引用对象引用的java对象。如果最后,年老区、Survivor-0、Survivor-1、Eden都满了(空间不够),则JVM会抛出“JVM堆空间溢出”(java.lang.OutOfMemoryError:Java heap space“,即堆空间满了,没有足够空间来存放创建的对象。
3、持久代(JVM中method area)
用于存放静态文件,如java类、方法、(静态)属性等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成和调用一些class,如hibernate,这时,需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPerSize=进行设置
年轻代和年老代组成了堆内存。
永久代则是非堆内存的组成部分。主要存放加载Class类及对象如class本身,method,field等等。
子系统分别是ClassLoader和ExecutionEngine,两个组件是Runtime Data Area和Native Interface,其中,Runtime Data Area中就包含了我们常说的JVM内存。
Runtime Data Area又将内存分为不同的区域,用户存储不同的数据:
Method Area —— 方法区,被ClassLoader所装载的class文件以及相关的方法信息、域信息、静态变量等都存放在这个区域内。该区域是所有java线程共享。
当虚拟机装载某个类型时,它使用类装载器,定位对应的class文件,然后读入这个class文件内容并传输到虚拟机中,虚拟机会提取其中的类型信息,并将这些信息存储到方法区。该类型中的类(静态)变量同样也存储到方法区中。因为被所有线程共享,要考虑多线程访问的同步问题。
Heap —— 堆区,用来存放java对象和数组,通常所说的GC(垃圾回收器)就是针对该区域,一个java虚拟机实例只有一个堆,直接由java虚拟机进行管理,在虚拟机启动的时候创建,该区域被所有线程共享。堆可以动态的分配内存大小,存取速度比较慢。
每一个java程序独占一个jvm实例,每一个jvm实例只有一个堆空间,因此此java程序的所有线程共享这个堆。因此每个java程序都有自己独立的堆空间,不会彼此干扰。但是同一java程序的多个线程都共享着一个堆空间,就得考虑多线程访问对象(堆数据)的问题(还有,并发访问静态属性、单例等等,具体情况具体分析)。
Stack —— 栈区,用来存放JVM内存指令,每个线程都有自己的栈。优势是,存取速度比较快,栈里面的数据可以共享,但是内存中的数据大小和生存期必须是确定的,缺乏灵活性。
java程序以帧为单位保存线程的运行状态。虚拟机只会对java stack执行两种操作:以帧为单位的压栈或出栈。每当线程调用一个方法的时候,就对当前状态作为一个帧保存到java stack中(压栈),当调用一个方法返回时,从java stack中弹出一个栈(出栈)。栈的大小有一定的限制,可能会出现StackOverFlow的问题。
Program Counter Register ——程序计数器, 每一个线程都有自己的PC寄存器,是该线程启动时创建的。PC寄存器的内容总是指向下一条被执行的指令的地址。
Native Method Stack ——本地方法栈, 保存本地方法进入区域的地址。对于一个运行中的java程序而言,它还可能用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时,它就进入了一个全新的并且不受虚拟机控制的世界。本地方法可能通过本地方法接口来访问虚拟机的运行时数据区,还可以做任何它想做的事情。比如调用寄存器、在操作系统中分配内存等等。总之,本地方法具有和JVM相同的能力和权限。
通常,可以将JVM分为堆区和非堆区,堆为上面的Heap区域,剩下的都是非堆区域。GC主要针对的是堆区域。
垃圾分代回收算法
基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年轻代、年老代、持久代,对不同生命周期的对象使用不同的算法进行回收。
java的内存模型分为:
Young(年轻代)
Tenured(年老代)
Perm(永久代)
1、年轻代(JVM中heap的一部分)
年轻代分为三个区,一个Eden区,两个Survivor区。大部分对象在Eden区中生成,当Eden满了的时候,程序又需要创建新的对象,此时JVM的垃圾回收器将对Eden区域进行垃圾回收,将Eden区中不再被其它对象所引用的对象进行销毁工作。将还有其它对象引用的对象将被移动Survivor-0区(两个中的一个,Survivor区用于存放垃圾回收器回收时幸存下来的对象),当这个Survivor-0区满了的时候,进行垃圾回收销毁没有被其它引用对象引用的java对象,此区的存活的对象将被移动到另一个Survivor-1区,如果Survivor-1区有足够空间就放到Survivor-1区,如果Survivor-1也满了,JVM会对Survivor-1进行垃圾回收,销毁没有被其它引用对象引用的java对象,将幸存的java对象移动到养老区。
2、年老代(JVM中heap的一部分)
年老代存放的是从年轻代存活的对象。一般来说年老代存放的都是生命周期比较长的对象。
如果从Survivor-1移动到年老代的时候,年老代有足够空间则放到年老区,如果年老区没有足够空间,则JVM的垃圾回收期会对年老区进行垃圾回收,销毁没有被其它引用对象引用的java对象,并保留那些被其它引用对象引用的java对象。如果最后,年老区、Survivor-0、Survivor-1、Eden都满了(空间不够),则JVM会抛出“JVM堆空间溢出”(java.lang.OutOfMemoryError:Java heap space“,即堆空间满了,没有足够空间来存放创建的对象。
3、持久代(JVM中method area)
用于存放静态文件,如java类、方法、(静态)属性等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成和调用一些class,如hibernate,这时,需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPerSize=进行设置
年轻代和年老代组成了堆内存。
永久代则是非堆内存的组成部分。主要存放加载Class类及对象如class本身,method,field等等。
相关文章推荐
- JVM内存结构
- [置顶] JVM(2): JVM 内存结构
- JVM内存结构浅析
- JVM理论与实践【内存结构】
- JVM(2):JVM内存结构
- JVM内存结构
- jvm内存结构(译)
- JVM(2):JVM内存结构
- 浅析JVM内存结构和6大区域
- java的线程安全、单例模式、JVM内存结构等知识学习和整理
- JVM内存逻辑结构
- JVM--类执行机制与JVM内存组成结构
- Java虚拟机详解02----JVM内存结构
- JVM结构、内存分配、垃圾回收算法、垃圾收集器
- java中OutofMemoryError和JVM内存结构
- [置顶] 深入理解JVM之一:Java内存结构
- JVM(2):JVM内存结构
- 【Java 之 JVM】Java内存结构概述
- Java JVM:内存结构和相关参数
- 关于Java虚拟机二三事(一)---Java技术体系及JVM内存结构