文章目录
java开发3~5年工作经验面试题
关于java虚拟机
平时我们的Java文件是如何运行的?
public class Math{
public static final int data=666;
public static User user = new User();
public int compute(int a,int b){
//一个方法对应一块栈帧内存区域
return a+b;
}
public static void main(String[] args){
Math math = new Math();
math.compute(1,2);
}
}
Java文件由JVM编译成class文件。。。
堆:当我们创建一个对象时,会把对象放在堆里面。
栈(线程):当执行一个方法时,会在栈中给该方法分配一块内存区域,这个内存区域暂且称为小W
栈帧:小W相当于一个先进后出的队列,执行A方法时,会创建一个栈帧,小W会为该栈帧分配区域用于储存A方法的局部变量,如果A方法里调用了B方法,然后执行到了B方法时,再创建一个B方法的栈帧,小W会为该栈帧分配区域用于储存B方法的局部变量,执行完B方法后,该栈帧会被删除,意为出栈,最后执行完A方法后,删除A方法的栈帧。
对象是存储在堆里,局部变量存储在局部变量表里,那如果局部变量是一个对象怎么搞的?
当然是先把对象存储到堆里,然后把该对象的在堆中的地址或引用存储在局部变量表中。同理,静态变量是存储在方法区中,如果静态变量是一个对象,先把对象存储到堆里,也是在方法区中存储的对象的引用。
程序计数器:是每个线程都独有的,程序计数器上面那一大块内存会挖一块分给每一个线程。
面试题案例:为什么每个方法区都要有一个程序计数器?
比如一个方法执行到了第五行的代码,突然出现一个优先级跟高的线程夺走了CPU分片,该方法会挂起,当优先级高的方法执行完毕后会继续执行该方法,程序计数器的作用就是标记该方法执行到哪里了,要接着继续执行下去。
方法区:存放常量、静态变量和类信息
本地方法栈:和栈没什么区别,唯一的区别是,本地方法栈是给native修饰的方法分配空间的。
堆区
堆区分为年轻代和老年代。
提一个概念:可达性分析算法(minor gc)
将GC ROOTS对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的对象都是垃圾对象。
GC ROOTS根节点:线程栈的本地变量、静态变量、本地方法栈的变量等等。
上面的图示,字节码执行引擎执行class文件,但同时还会执行垃圾收集线程,收集垃圾的模式就是可达性分析算法,本来堆中的Eden区域存储着所有的对象,然后经过可达性分析算法后,将标记的非垃圾对象转移到 s0 区域中,Eden中剩下的对象都为垃圾对象,全部清理掉,继续接收存储新的对象。
s0区域经过可达性分析算法之后,将非垃圾对象转移到s1区域中,s0剩下的垃圾对象全部清理掉。
每进行一次可达性分析算法,筛选下来的对象的年龄就加一,如果年龄达到15之后,则存储在老年代空间中。
JVM调优具体调优什么?
减少full gc!
上面说的是minor gc垃圾回收算法,这里提到full gc垃圾回收算法
当老年代空间被占满之后会触发full gc垃圾回收,这时会停到所有的用户线程(STW)(即用户访问),专心回收整个堆中的垃圾对象,平时full gc需要的时间会很少,几乎没有感知,但是如果full gc花费时间长的话,用户角度就是死机状态,所以要优化!
面试题案例: