java 虚拟机

来源:互联网 发布:奥尼尔新秀赛季数据 编辑:程序博客网 时间:2024/06/13 02:17

java内存分为 堆,虚拟机栈,本地方法栈,方法区,程序计数器

程序计数器是当前线程所执行的字节码的行号指示器,线程私有,每个线程有独立的程序计数器,互不干扰。
程序计数器是唯一一个不会有OutOfMemoryError的区域

虚拟机栈也是线程私有的,生命周期和线程相同。
虚拟机栈描述的是java方法执行的内存模型,每个方法在执行的时候回创建一个栈帧(stack frame )用于村村局部变量表,操作数栈,动态链接,方法出口等信息。每个方法从调用到执行完成的过程,都对应一个栈帧在虚拟机栈中入栈到出栈的过程。

局部变量表存储了编译器克制的各种基本类型(boolean、byte、char、short、int、long、double)、对象引用(referenece类型,他不等同于对象本身,可能是一个执行对象起始地址的引用指针、也可能是一个代表对象的句柄或类似的信息) 和returnAddress类型(指向了一个字节码指令的地址)

局部变量表所需的内存空间在编辑器件完成分配,当进入一个方法是,这个方法在帧中分配多大的局部变量空间是确定的,在方法运行期间不会改变局部变量表的大小。
这里有两种异常,如果线程请求的栈深度大于虚拟机允许的深度,将抛出stackOverFlowError异常。如果虚拟机栈动态扩展时无法申请到足够的内存,就会抛出OutOfMemoryError。

本地方法栈为虚拟机使用到native方法服务。

堆是迅疾管理内存最大的一部分,被所有线程共享的一块内存区域,在虚拟机启动时创建。次聂村区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。

java堆是垃圾回收器管理的胡中亚哦区域,1.7和之前的收集器采用分代手机算法,可细分为新生代老年代,新生代分为Eden,From Survivor、to survivor空间等。

方法区,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常亮、静态变量、即时编译器编译后的代码等数据。
对于jdk来说,方法区也可以叫做永久代,因为java的方法区是放在永久代里的。
字符串常量,原先是在永久代,从1.7开始移出。

运行时常量池是方法区的一部分。

直接内存,是NIO会用到的,直接使用堆外内存,避免在java堆和native堆之间来回复制数据,可提升性能。

对象创建。虚拟机需要new指令的时候,会先去检查能否在常量池定位到一个类的符号引用,并检查这个符号引用代表的类是否已被加载、解析、初始化过,如果没有,那必须按先执行对应类的加载过程。
类加载完毕后,会为新生对象分配内存怒。
指针碰撞和空闲列表,基于compact的收集器,使用指针碰撞算法,cms这类基于mark-sweep算法的收集器,通常采用空闲列表。

一个对象的对象头(Object header),包括这个对象是哪个类的实例、怎么找到类的元数据信息、对象的hase code、gc分带年龄等信息。

对象的内存布局
对象在内存中分为三部分:对象头,示例数据,对齐填充。
对象头包括,hashCode、gc分代年龄、锁状态标记、线程持有的锁、偏向锁id、偏向时间戳等。这些信息成为mark word。

对象的访问:程序通过栈上的reference数据来操作堆上的具体对象。分为句柄访问和直接内存访问(htspot使用这种)两种模式。

判断对象是否存活的算法:引用计数器,可达性分析算法。

可作为gc roots的对象包括如下几种
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中jni(native方法)引用的对象

引用方式:强软弱虚
强引用,只要引用存在,永远不会被回收。
软应用,当gc时,会被回收。
虚引用,当被垃圾回收期扫描扫到时,会被回收。

原创粉丝点击