Java Vitural Machine
方法区
用于存放被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等
方法区和Java堆一样,是各个线程共享的内存区域,垃圾回收在正常情况下极少会出现在该区域
收集垃圾也是对常量池的回收和堆类型的卸载。
> 运行时常量池
运行时常量池原是方法区的一部分(但最新的Jre对位置做了变动),class除了类的版本、
字段、方法、接口还有一些常量池,存放编译期产生的各种字面量和符号引用。
常用工具:Jconsole和VisualVM
堆
Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建,内存区域存放的时对象实例
Java堆也是垃圾收集器的主要管理区域,因此也被称为是GC堆,Java堆还可以细分成 新生代、
老年代,Eden空间,Suvivor空间(from和to)
堆大小 = 新生代(-Xms) + 老年代(-Xmx)
【默认新生代和老年代是1:2,但在G1中不存在固定值,两者而已通过 -XX:NewRatio配置】
新生代 = Eden + Survivor(from) + Suvivor(to)
【默认比例是:8:1:1,这个在G1中也不存在固定值】
GC有 Minor GC 和 Full GC(Major GC)
> Minor GC
发生在新生代的垃圾收集动作,一般采用复制算法,当一个对象被判定为死亡的时候,GC会收回这部分对象
的内存空间,新生代是GC收集的频繁产生阶段。对象在Eden出生后,经过一次Minor GC,会进入Survivor(from)
空间,再经过一次Minor GC年龄就会增加1,等到制定的次数后,会进入老年代,通过-XX:MaxTenuringThreshold
设置,默认值是15
> Full GC
Full GC一般发生在老年带,通常采用标记-清除算法,但,当JVM检测到空间不足时会自动触发一次Full GC,
该模式会使程序暂停,也叫 stop-the-world(Minor GC对程序是无感的)
虚拟机栈(JVM执行Java方法)
java方法执行的内存模型,每个方法执行都会创建一个栈帧(局部变量表、操作数栈、动态连接、方法出口),
每个方法从开始调用到结束都对用一个栈帧在虚拟机栈中入栈到出栈的过程。
虚拟机栈的生命周期与线程相同,每个Java方法执行的时候会创建一个栈帧,这个栈帧用来存储局部变量表、
操作栈、动态连接、方法出口等信息,每个方法被动用直到执行完成的过程,就对应着一个栈帧在虚拟机从
入栈到出栈的过程。
虚拟机栈中局部变量表部分,存放了编译期可知的各种基本数据类型、对象引用等,
局部变量表部分所需的内存空间在编译期完成分配
> StackOverflowError
线程请求的栈深度大于虚拟机所允许的深度,将会抛出该异常
> OutOfMemoryError
当扩展时候无法申请到足够的内存时会抛出OutOfMemoryError异常
本地方法栈(JVM执行本地方法)
HotSpot把本地方法栈和虚拟机栈合二为一
本地方法栈与虚拟机栈很类似,虚拟机栈时执行Java方法的服务,本地方法栈是执行Native方法的服务(非Java代码接口)
该栈也会抛出虚拟机栈抛出的两个异常。
程序计数器
当前程序执行字节码的行号指示器;
作用:当前线程所执行的字节码的行号执行器,字节码解释器通过改变基数器的值来选取下一条需要执行的字节码指令
分支、循环、跳转、异常处理等都通过程序计数器来完成。
> Java多线程
Java虚拟机多线程是通过线程轮流切换并分配出资源的方式实现的,任何时刻,一个处理器核心只会执行一条线程
中的指令,为了线程切换后能恢复到正确的执行位置,每个线程都需要一个独立的程序计数器。