1.jvm内存模型按照线程私有与否划分为两类,线程私有类内存(线程栈,程序计数器,本地方法栈)和线程共享内存(堆,方法区or元空间)两大类;
线程栈:当类开始执行main方法后,字节码执行引擎就会为当前线程分配一块内存区域,该区域详细又可以根据执行的方法为main方法的后续方法分配栈空间,我们将这些相互隔离的一个个内存空间叫做栈帧,这些栈帧的内存空间具体可分为四块,分别是局部变量表,操作数栈,动态链接,方法出口,其中局部变量表我们可以简单的理解为数组,存放一个个变量的引用地址,操作数栈是程序运行期间操作数临时存放的地方,包括入栈和出栈,入栈是将操作数压入栈顶,出栈的目的是将这些操作数交给cpu去执行相关的四则运算操作,操作后的结果又会被压入栈中,等待后续操作,这些操作数会频繁的在操作数栈和局部变量表中交换存取,动态链接相当于程序运行期间将字面常量代表的内存地址解析到对应的内存代码块,链接执行,
程序计数器的设计是为了解决多线程场景下由于线程上下文切换时记录当前线程执行到字节码的行号,便于后期程序在原来执行的基础上继续执行,
本地方法栈是存放native方法相关的东西而分配的空间,
堆一般用来存放新创建的对象
方法区用来存放类信息,静态变量,常量池等信息
栈与堆得关系大致可以理解为栈中局部变量持有堆上对象的内存地址,堆与方法区的关系可以理解为堆上的对象被方法区的变量进行引用
2.关于堆得详细说明,堆根据对象存在的时间划分为新生代和老年代,新生带占堆总空间的1/3,老年代占用2/3,新生代又可划分为eden区,约占8/10,s1,s2各占1/10,对象总是在eden区诞生,当对象不断产生最终这8/10的空间不足以存放这些对象时,会触发monitor gc进行垃圾回收,垃圾回收过程中将一些与引用对象相关联的对象树整个迁移到s1区,并将该对象的年龄+1,同时回收掉垃圾对象,在回收对象时,会存在stw问题,即就是stop the word,就是暂时停止用户线程,由垃圾回收机制负责回收掉垃圾后用户线程再继续执行,当然,jvm设计这个策略是为了解决线程结束后栈内存会被释放,这时候之前垃圾回收收集的引用句柄也就无效了,无法找到垃圾对象,所以,无法在进行gc的时候不停止用户线程。当对象不断产生第二次触发monitor gc时,回收器会回收eden区和s1区有用的对象到s2区,当对象年龄超过15后会被放入老年代,当老年代空间满了的时候会触发full gc,对无用垃圾进行回收,若发现老年代这些对象仍然有用,则会报出oom异常