Java很强大,原因有很多。其中之一就是“write once, run anywhere”,而这一切都离不开jvm。
jvm是java虚拟机,主要分为三个部分:类加载器,执行引擎,运行时数据区。
我们在面试中被问到的最多的就是运行时数据区。
运行时数据区主要分为五个部分:虚拟机栈,本地方法栈,堆,方法区,程序计数器。其中本地方法栈、虚拟机栈、程序计数器是线程私有的,方法区和堆是线程共享的。
1 虚拟机栈
虚拟机栈是由一个个栈桢组成,程序中的每一个方法在运行的时候都会被压入虚拟机栈,也可以看成每一个运行的方法就是一个栈桢。在栈桢中包含四个组成部分,局部变量表、动态链接、操作数栈、方法出口。每一个方法执行完之后就会立即出栈。因此栈不存在垃圾回收,但是栈有深度,可能出栈stackOverFlow。
2 本地方法栈
本地方法栈与虚拟机栈类似。
3 程序计数器
在我们的源码被编译为class去执行的时候,我们的代码执行顺序就是通过程序计数器来保证的。
4 方法区
方法区主要用来存储运行时的常量池、静态变量、类信息、JIT编译后的代码等数据。
5 堆
堆中主要分为两个区域,新生代和老年代。
新生代又分为三个区域,eden、survovir from、survivor to。
第一次gc
eden主要用于生成新对象,在该区域满了之后,会进行一次minor gc,回收掉无用的对象,剩下的存放到from中。
第二次gc
等到下次eden满了触发gc的时候,把eden中存活的对象复制到to中,from中存活的对象判断其age是否到了阈值,如果到了就存放到老年代,如果没到就把对象复制到to中并且对象age+1,保证eden和from是空的状态。如果此时to也满了,会把to的对象复制到老年代中。
第三次gc
过了一段时间,eden又满了,执行了gc,这时候把eden中存活的对象又放入from中。
来来回回执行上三个步骤,直到老年代满了,会触发major gc(full gc)。
网友评论