java虚拟机理解(一)——内存模型与对象创建

来源:互联网 发布:淘宝卖快排配件犯法吗 编辑:程序博客网 时间:2024/05/29 09:49

      JVM是java语言一项重要产物,正是由于JVM的存在,才使得java语言的跨平台特性。闲话少说,先来总结一下java虚拟机的内存模型。

1) 再说java内存模型

      运行时数据区域通常分为:方法区和堆以及虚拟机栈、本地方法栈、程序计数器。以上几个部分构成运行时数据区。先来看看各部分负责的功能。

程序计数器:这个比较好懂,就是PC指针。当前线程所执行代码的行号指示器,通过计数器来取下一条需要执行的字节码指令。

java虚拟机栈:线程私有,生命周期与线程相同,每个方法在执行的同时都会创建一个帧栈,用于储存局部变量表、动态链接、方法出口等信息。这个也好理解,解释为方法的运行会创建相适应的方法栈区。局部变量表中会存储各种基本类型(boolean byte char short int float double long),还包括引用类型该reference是指向一个对象起始地址的引用指针(java Hotspot虚拟机是采用直接地址方式)。需要注意的是若线程请求栈深度大于虚拟机深度,将会抛出StackOverflowError异常。

本地方法栈与虚拟机栈不同之处在于虚拟机栈为虚拟机执行字节码服务,本地方法栈则为虚拟机栈的Native方法服务。有的虚拟机直接将本地方法栈和虚拟机栈合二为一了。

java堆:虚拟机中管理内存最大一部分。属于所有线程共享,几乎所有对象实例都在堆上分配内存。这在java垃圾回收算法中是非常重要的一部分。

方法区:也是所有线程共享内存区域。用于存储被虚拟机加载类信息、常量、静态变量、编译后的代码等数据。通常将方法理解为堆的一个逻辑部分,但是却与堆有区别。

运行时常量池:属于方法区的一部分,用于存放编译期生成的各种字面量和符号引用。

       以下是运行时内存模型的一个简图(注:以上参考于教材《深入理解Java虚拟机——JVM高级特性与最佳实践(第2版)》周志明 著)

这里写图片描述

2)对象创建过程

      对象创建过程是在堆上分配内存,线程共享内存。下面是对象创建的几个步骤:

step 1)虚拟机遇到new指令时,首先在常量池查看是否能定位到一个类的符号引用,并且检查这个符号引用的代表的类是否已经被加载、解析、和初始化。如果没有,需要进行类加载操作。

step 2) 接下来虚拟机为对象在堆上分配内存。通常有两种内存分配方式:指针碰撞和空闲列表。

       关于指针碰撞:连续空闲内存,假设内存绝对规整,空闲和使用过的内存时分开的,使用指针作为分界点的指示器,分配方式是将临界指针向空闲内存内存进行偏移,这过程称之为内存碰撞。用以下简图表示:

这里写图片描述

      关于空闲列表:这种方式通常发生在空闲内存和分配内存交互的情况下,此时无法使用指针碰撞,JVM此时可提供空闲列表的方案对创建的对象分配内存。通过维护一个列表,记录哪块内存可用,需要分配时就从可用内存中分一块进行创建对象。

      注意在分配内存中需要进行同步处理,因为不同线程可能同时对堆上的指针进行操作,通过同步保证对象在堆上分配内存不会紊乱。

step3)虚拟机对对象头部进行设置。通常包括所属类、对类的元数据信息、对象GC年代。这里有一个关于init操作,但在执行Init方法之前此时对象刚刚创建,对象中的所有字段都是0,执行new之后,对象才整正初始化。

关于对象内存布局。三大部分:对象头、实例数据、对齐填充。用以下简图进行表示。

这里写图片描述

       以上就是内存模型和对象创建一些要点,关于对象创建过程,这里面涉及一些较复杂的操作。例如初始化过程,类加载等,这些慢慢学习了。

0 0
原创粉丝点击