在Java虚拟机的帮助下不需要手动为每个对象分配内存和释放内存,这样不容易出现内存泄漏的情况。

在Java虚拟机运行时会管理以下几个区域

线程间隔离的:虚拟机栈、本地方法栈、程序计数器

线程间共享的:方法区、堆

程序计数器:当前线程执行的字节码行号指示器。

每条线程均需要一个独立的程序计数器来记录当前执行的位置

如果正在执行的是一个Java方法则计数器只想位置是字节码的地址,如果是Native方法 则计数器值为空

Java虚拟机栈:线程私有,描述Java方法执行的内存模型。方法从调用到执行完成的过程对应着一个栈帧入栈出栈的过程。每个方法在执行的同时会创建一个栈帧来存储方法的局部变量表、操作数栈、动态链接、方法出口等信息

关键在局部变量表:存放着编译期可知的各种基本数据类型(方法中使用到的数据类型)、对象引用(reference类型可能指向对象起始地址的引用指针或指向代表对象的句柄或其他和此对象相关的位置)、returnAddress类型(指向一条字节码指令的地址)

局部变量表所需空间在编译期间完成分配,方法执行时在栈帧中分配多少空间是已知且固定的,运行期间不会改变局部变量表的大小。64位长度的long和dubbo类型数据占两个局部变量空间其他类型占1个     可能出现异常 堆栈溢出和内存不足 StackOverflowError、OutOfMeoryError

当方法递归引用过深将有可能会出现堆栈溢出

 本地方法栈:线程私有!!! 不要被名字迷惑!!! 为虚拟机使用到的Native方法服务。 本地方法栈也有可能抛出StackOverflowError和OutOfMemoryError(有的虚拟机将本地方法栈和虚拟机栈合二为一泪如Sun HotSpot 因为他们功能作用基本一致 只是服务对象有类别之分)

 Java堆:线程共享 虚拟机管理的最大的一块内存区域。 基本所有的在程序中创建的对象实例和数组都在堆上分配内存

细分为新生代、老年代  新生代还可分为一块Eden区和两块Survivor区域(8:1:1)。 GC垃圾收集器也是主要采用分代收集算法回收该块内存 可以使用-Xmx -Xms设置堆大小 

 方法区:线程共享 存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码  也可称之为永久代(在HotSpot虚拟机上GC分带手机算法扩展至方法区,其他虚拟机不存在永久代概念。)1.7版本中方法区中的字符串常量池已经从方法区移至堆中

直接内存:JDK1.4加入的NIP类 引入基于通道和缓冲区Buffer的I/O方式 可以使用Native函数库直接分配堆外内存 通过存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作

对象内存布局:对象在内存中的布局分为三块:对象头、实例数据、对其填充

对象头存放自身运行时数据 :哈希码、GC分代年龄、锁状态标志、线程持有锁、偏向线程ID、偏向时间戳 固定长度 32或64位(视操作系统定)

对象实例:对象在程序中真正有意义的部分

对齐填充:保证对象起始地址是八字节的整数倍

对象访问定位通过虚拟机栈存储的reference类里面的对象地址或者对象句柄地址再通过句柄存储地址访问堆中对象