JVM运行时数据区
线程共享:所有线程能访问这块内存数据,随虚拟机或GC而创建和销毁
线程独占:每个线程都会有它独立的空间,随线程生命周期而创建和销毁
线程安全问题:共享资源的抢占、线程共享的内存区域
方法区
方法区作用:存储加载的类信息、常量、静态变量、JIT编译后的代码等数据
GC:方法区存在垃圾回收,但回收效率低;回收主要针对常量池的回收。和类型的卸载;当方法区无法满足内存需求时,报OOM。
方法区属于Java虚拟机协议,比如Hotsport虚拟机是对其具体实现,实现的时候会去实现方法区,堆内存,垃圾回收GC,永久代是对方法区的实现,新生代,老年代对堆内存实现,jdk1.8就变了,以元数据来实现方法区。
堆内存
作用:唯一的目的就是存放对象实例,几乎所有对象、数组都是在这里存放
对于大多数应用来说,堆是JVM管理的内存中最大的一块内存区域,也是最容易OOM的区域
大多数JVM都将堆实现为大小可扩展的(通过-Xmx、-Xms)控制
思考问题一:堆中存储了对象,那到底存储了什么?
Java对象在内存中的布局
思考问题二:对象何时被回收?
1、引用计数法(无法解决两个对象相互引用无法回收问题,导致内存泄露,JVM肯定不回去使用这种方式)
2、可达性分析算法
主流的商用程序语言(Java、C#)都是通过可达性分析算法来判定对象是否存活的,
GC Roots可以是:1、虚拟机栈;2、方法中静态属性引用对象;3、方法区中常量引用对象;4、Native方法引用对象。
虚拟机栈
虚拟机栈:线程中方法执行的模型,每个方法执行时,就会在虚拟机栈中创建一个栈帧,每个方法从调用到执行的过程,就对应栈帧在虚拟机栈中从入栈到出栈过程。
Java线程本质是:从逻辑上来理解,开启一个Java线程,new Thread(()->{线程执行的业务代码})
main->show()->show1()->shou2()这样的调用链路,先进后出,就是栈,也就是代表虚拟机栈方法调用逻辑
虚拟机栈中的元素在逻辑上代表方法,代表方法的栈元素就叫做栈帧。
局部变量表
动态链接
方法里的局部变量并不是一致存在,只有在方法调用的时候才会存在,只有在方法调用才会有方法入栈。
返回值地址
本地方法栈、直接内存
本地方法栈:和虚拟机栈功能类似,虚拟机栈是为虚拟机执行Java方法而准备,本地方法栈是为虚拟机使用Native本地方法而准备的。
直接内存:JVM之外的内存,开发人员自己分配内存
class文件结构
现在看下整个过程执行流程
切换上下文方式,程序计数器来跟踪。