Java内存根据线程独有还是共有可分为两大类:
方法区和堆是线程共有的。
虚拟机栈,程序计数器,本地方法栈是线程独有内存。
也有人大致把它分为堆区,栈区和静态区。
堆区是所有对象实例及数组所在的地方,所有线程共享,由虚拟机启动时创建。垃圾回收就主要发生在这里。
方法区(Method Area)主要存放类信息,常量,静态变量等数据,所有线程共享。运行时常量池就是方法区的一部分。
虚拟机栈就是常说的栈区。各个线程都有自己的虚拟机栈。线程方法执行时会以栈帧(存放局部变量表,操作数栈,方法出口等)的形式入栈,执行完出栈。
局部变量就存放在相应方法的栈帧里面。栈的深度是有限的,当栈帧过多时(递归调用常出现)就此抛出StackOverFlow异常。
本地方法栈和虚拟机栈相似,不过是为Native方法服务,HotSpot虚拟机就直接把二者合二为一。
程序计数器(Program Counter Register)也是各个线程独有。因为程序是顺序执行,方法调用及并行时会来回跳转。所以就需要有一个计数器来记录程序执行位置。
对象创建过程是什么呢?
1. 虚拟机要检查该对象的类是否已被加载,如果没有执行加载动作。
2. 给对象分配内存空间,此时要注意内存分配是否成功及并发问题(堆是所有线程共享)。
3. 初始化。(默认初始化0值)
那么具体一个对象在HotSpot VM内存中是如何存储的呢?
对象在内存中主要有三部分组成:对象头(32bit),实例数据和填充部分。
对象头主要存放两部分信息:1, 运行时数据,如哈希码,锁状态等; 2, 类型指针, 即指向它所属类元数据的指针(反射会用到)。
实例数据就是代码中所定义的各种类型字段的内容。
填充部分不是必然有的,主要是保证对象正好是8字节的整数倍。
访问时,有句柄访问和直接指针访问两种方式,HotSpot使用的是直接指针访问。