Java语言区别于其他计算机语言的最大特点就是面向对象性,也被称为与平台无关的编程语言,java能实现这样的特点,就是因为JVM虚拟机的作用,因此关于JVM的知识点都是需要大家掌握的。下面整理了10道JVM面试题,是在java面试中考察几率最大的题目,一起来学习吧。

1、什么情况下会发生栈内存溢出?

答:(1)栈是线程私有的,他的生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。局部变量表又包含基本数据类型,对象引用类型;

(2)如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常,方法递归调用产生这种结果;

(3)如果Java虚拟机栈可以动态扩展,并且扩展的动作已经尝试过,但是无法申请到足够的内存去完成扩展,或者在新建立线程的时候没有足够的内存去创建对应的虚拟机栈,那么Java虚拟机将抛出一个OutOfMemory异常;

(4)参数-Xss 去调整JVM栈的大小。

2、介绍JVM内存模型

答:JVM内存结构如下:

JVM篇 java面试总结之 java面试题jvm_JVM

程序计数器:当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有。

Java虚拟栈:存放基本数据类型、对象的引用、方法出口等,线程私有。

Native方法栈:和虚拟栈相似,只不过它服务于Native方法,线程私有。

Java堆:java内存最大的一块,所有对象实例、数组都存放在java堆,GC回收的地方,线程共享。

方法区:存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码数据等。(即永久带),回收目标主要是常量池的回收和类型的卸载,各线程共享。

3、JVM内存新生代中为什么要分为Eden和Survivor?

答:(1)如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major

GC.老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多,所以需要分为Eden和Survivor;

(2)Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor

GC还能在新生代中存活的对象,才会被送到老年代;

(3)设置两个Survivor区最大的好处就是解决了碎片化,刚刚新建的对象在Eden中,经历一次Minor

GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor

GC,Eden和S0中的存活对象又会被复制送入第二块survivor space

S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。

4、JVM的永久代中会发生垃圾回收吗?

答:垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full

GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免Full

GC是非常重要的原因。请参考下Java8:从永久代到元数据区 (注:Java8中已经移除了永久代,新加了一个叫做元数据区的native内存区)。

5、什么是类加载器,类加载器有哪些?

答:实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。主要有以下四种类加载器:

(1)启动类加载器(Bootstrap ClassLoader)用来加载java核心类库,无法被java程序直接引用;

(2)扩展类加载器(extensions class loader):它用来加载java的扩展库。Java

虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载java类;

(3)系统类加载器(system class loader):它根据java应用的类路径(CLASSPATH)来加载Java类。一般来说,Java

应用的类都是由它来完成加载的。可以通过ClassLoader.getSystemClassLoader()来获取它;

(4)用户自定义类加载器,通过继承 java.lang.ClassLoader类的方式实现。

6、简述java类加载机制?

答:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的java类型。

7、类加载器双亲委派模型机制?

答:当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类去加载,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。

8、Java对象创建过程?

答:(1)JVM遇到一条新建对象的指令时首先去检查这个指令的参数是否能在常量池中定义到一个类的符号引用,然后加载这个类;

(2)为对象分配内存。一种办法“指针碰撞”、一种办法“空闲列表”,最终常用的办法“本地线程缓冲分配(TLAB)”;

(3)将除对象头外的对象内存空间初始化为0;

(4)对对象头进行必要设置。

9、对象分配的规则?

答:(1)对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC;

(2)大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存);

(3)长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,如果对象经过了1次Minor

GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,直到达到阀值对象进入老年区。

(4)动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。

(5)空间分配担保。每次进行Minor

GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full

GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor GC,如果false则进行Full GC。

10、描述一下JVM加载class文件的原理机制?

答:JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始化语句。

类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从Java

2(JDK

1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。

JVM使java成为应用程序可以运行在任意的平台变成可能,不需要程序员为每一个平台单独重写或者是重新编译。所以需要大家对JVM的内容熟练掌握,上面的JVM面试题是学习虚拟机的基础知识,也是在java面试中常考到的题目,希望朋友们可以好好学习JVM的相关知识,同时也可以更多的学习和关注java面试题,这样才能在众多面视者中脱颖而出。