JVM在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。

线程私有:虚拟机栈,本地方法栈,程序计数器。线程共享:方法区,堆。

方法区:Class,静态常量,静态变量

程序计数器:指向当前线程正在执行字节码指令的地址

虚拟机栈:存储当前线程运行方法所需的数据、指令、返回地址。大小限制:-Xss

栈帧:

  • 局部变量表

  • 操作数栈

  • 动态连接

  • 完成出口

Java解释执行是栈(操作数栈):兼容性好,效率差

C是寄存器(硬件):运算快,移植性差

本地方法栈保存的是native方法的信息。当一个JVM创建的线程调用native方法后,JVM不再为其在虚拟机栈中创建栈帧,JVM只是简单地动态连接并直接调用native方法。虚拟机规范无强制规定,各版本虚拟机自由实现,HotSpot直接把本地方法栈和虚拟机栈合二为一。

方法区:类,静态变量,静态常量,即时编译期编译后的代码

Java堆:对象实例,数组

Java堆大小参数设置:-Xmx 堆区内存可被分配的最大大小 -Xms 堆区内存初始内存分配的大小

<= JDK1.7 永久代

= JDK1.8 元空间

永久代受限于JVM堆大小,元空间受限于机器内存

元空间:

好处:方便拓展,坏处:挤压堆空间

直接内存,堆外内存 DirectBuffer nio 本地内存

栈溢出,StackOverflow 堆溢出,本地内存溢出,方法区溢出

虚拟机优化:方法内联,栈帧之间数据共享

A方法传递参数给B方法 A局部变量表 -> B操作数栈 同一块内存区域

finalize方法只能被执行一次。finalize线程执行优先级比较低。