最近参加面试被问到了这个经久不衰的问题。回答后自觉不是那么详细,所以在这里整理一次,虽然这个知识点网上已经太多太详细了,所以这边简单总结一下在面试中如何简短并准确的回答给你的面试官。
JVM中包含
1.方法区
方法区中存放已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。堆的逻辑部分,线程共享,长期 存在。-XX:PermSize -XX:MaxPermSize
2.虚拟机栈
对每个将要执行的方法创建栈帧,存储方法局部变量,操作数栈,动态链接,方法出口。-XSs
3.本地方法栈
和虚拟机栈类似,非java中的方法,同样存储本地方法的局部变量,操作数栈,动态链接,方法出口。
4.堆
存储对象,线程共享,内存中唯一,JVM启动时创建,细分新生代,老年代。-Xms -Xmx -Xmn
5.程序计数器
程序计数器记录当前线程执行的位置(尤其在多线程中),实现代码的流程控制。
6.执行引擎(*)
底层操作系统读改写堆。
7.本地接口(*)
底层操作系统操作程序计数器,cpu时间片调用。
再说点加分项吧,接着面试官必问GC
1.说到了垃圾处理,怎么样找出垃圾?
算法两种:引用计数,可达性分析。
2.有哪些回收方法?
Mark-Sweep标记-清除:删除无停顿时间,但造成内存碎片。
Copying复制算法:不删除,适合大量对象回收,新生代回收算法。
Mark-Compact标记-整理:解决内存碎片,增加停顿时间
Generational Collection分代收集:
1.Young Generation:
survivor0
survivor1
Eden
用于存放新创建的对象,采用复制回收方法,如果在s0和s1之间复制一定次数后,转移到年老代中。这里的垃圾回收叫
做minor GC;
2.Old Generation:
Tenure
这些对象垃圾回收的频率较低,采用的标记整理方法,这里的垃圾回收叫做 major GC.
3.Permanent Generation:
存放Java本身的一些数据,当类不再使用时,也会被回收。
*重点是新生代的算法
在新生代中,分为三个区:Eden, from survivor, to survior。
1. 当触发minor GC时,会先把Eden中存活的对象复制到to Survivor中;
2.然后再看from survivor,如果次数达到年老代的标准,就复制到年老代中;如果没有达到则复制到to survivor中,如果to survivor满了,则复制到年老代中。
3.然后调换from survivor 和 to survivor的名字,保证每次to survivor都是空的等待对象复制到那里的。
jvm五大区:
其中方法区和堆内存是线程共享的,本地方法栈、虚拟机栈、程序计数器是线程独占的
堆内存可以细分为:
有人可能会问永久代到底是属于堆呢,还是属于方法区呢,其实在逻辑上永久代在逻辑上是和堆分开的,但物理上永久代是属于堆的。
年轻代大小默认比例:eden:from survivor:to survivor=8:1:1
jdk1.7及以前:堆内存=eden+from survivor+to survivor+paroldgen+perm
jdk1.8:堆内存=eden+from survivor+to survivor+paroldgen 元空间不在虚拟内存中,在本地内存中
在jdk1.7中开始了为对方法区的移除做准备,jdkk1.7中将常量池移到堆中。
在jdk1.8中彻底移除了方法区,增加元空间MetaSpace(其作用与方法区相似)
对象分配:对象先会分配在eden(大对象直接进老年代),当eden满了,触发GC,存活的对象进入from survivor,from survivor满了,触发GC,存活的对象进入to survivor,to survivor满了,触发GC,存活的对象进入from survivor,这样from survivor和to survivor总有一个为空,并且每次GC对象的年龄阈值都会加一,默认到15时对象进入老年代,当老年代到达一定百分比时触发GC