JVM虚拟机面试题

1入门部分

1.1为什么要学习JVM?
学习JVM主要有两方面的原因:
1.从自身利益出发来讲,学习JVM主要是因为中高级程序员在面试时会提到相关问题。
2.从提升自身技术水平来讲,深入理解JVM可以帮助我们从平台的角度去提高解决问题的能力。例如
(1)有效防止内存泄漏(Memory leak)
(2)优化线程锁的使用(Thread Lock)
(3)科学进行垃圾回收(Garbage collection)
(4)提高系统吞吐率(throughtput)
(5)降低延迟(Delay),提高性能(performance)

1.2你了解哪些JVM产品?
市场主流JVM主要有:
1.由Sun公司研发,于2010年被Oracle公司收购的HotSpot VM
2.由BEA公司研发,于2008年被Oracle公司收购的JRockit VM
3.IBM内部使用的J9 VM
4.TaobaoJVM:ALiJVM团队开发,基于OpenJDK开发了AlibabaJDK
注:HotSpot是目前应用最官方,最主要的一款JVM虚拟机

1.3JVM的构成有哪几部分?
JVM主要由四个部分组成:
1.类加载系统(ClassLoader System),主要负责将类加载到内存中去。
2.运行时数据区(Runtime Data Area),主要负责存储数据的信息(例如对象、方法等等)。
3.执行引擎(Execution Engine),负责主要负责解释执行的字节码/执行CG操作等。
4.本地库交界口(Native Interface)负责融合不同的编程语言为Java所用。

2类加载部分

2.1你知道哪些类加载器?
1.BootstrapClassLoader:启动类加载器/根类加载器
2.ExtClassLoader:扩展类加载器
3.AppClassLoader:应用程序加载器/系统类加载器

2.2什么是双亲委派类加载模型?
1.概念:类加载器受到了类加载的请求后,不会自己先行加载,而是将此请求委托给父类加载器去执行;如果父类加载器也存在父类加载器,则继续向上委托,一次递归,请求最终到达顶层的启动加载器;如果父类加载器可以完成类加载任务,则成功返回。如果不能完成,子加载器才尝试自己去加载。父类加载器一层层向下分配任务,如果子类加载器能加载则加载此类。如果将加载任务分配到系统类加载器仍无法加载此类,则抛出异常。
2.意义:避免类的重复加载。
3.图解:
JVM虚拟机面试题_第1张图片

2.3双亲委派方式加载类有什么优势、劣势?
1.优点
(1)避免类被重复加载,确保一个类的全局唯一性
(2)保护程序的安全,防止核心API被随意的篡改
2.缺点
由于检查类是否加载的委派过程是单向的,这会导致顶层的类加载器无法访问底层的类加载器所加载的类。

2.4描述一些类加载时候的基本步骤是怎样的?
按照Java虛拟机规范,从class文件到加载到内存中的类,到类卸载出内存为止,它的整个生命周期包括如下7个阶段:
JVM虚拟机面试题_第2张图片

其中,验证,准备,解析3个部分统称为链接(Linking)
JVM虚拟机面试题_第3张图片

2.5什么情况下会触发类的加载?
以下情况会触发类的初始化:
1.遇到new,getstatic,putstatic,invokestatic这4条指令;
2.使用java.lang.reflect包的方法对类进行反射调用;
3.初始化一个类的时候,如果发现其父类没有进行过初始化,则先初始化其父类(注意!如果其父类是接口的话,则不要求初始化父类);
4.当虚拟机启动时,用户需要指定一个要执行的主类(包含main方法的那个类),虚拟机会先初始化这个主类;
5.当使用jdk1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则先触发其类初始化;

2.6类加载时静态代码块一定会执行吗?
不一定。类加载的方式有多种,并不是每一种方式都能执行静态代码块。
在执行的时候加上以下一句JVM的运行参数,可以观看类加载过程
-XX:+TraceClassLoading。
类加载时是否会执行静态代码块取决于加载的方式。

2.7如何理解类的主动加载和被动加载?
主动/被动加载又称为主动/被动引用

类的主动引用有(一定发生类的初始化)
1.new一个对象
2.调用类的静态成员(除了final常量)和静态方法
3.使用java.lang.reflect包的方法对类进行反射调用
4.当虚拟机启动,java Hello,则一定会初始化Hell类,先启动main方法所在的类
5.当初始化一个类,如果父类没有被初始化,则会先初始化它的父类

类的被动引用(不会发生类的初始化)
1.当访问一个静态类时,只有真正声明该静态类的域才会被初始化
2.通过数组定义类的引用,不会触发该类的初始化
3.引用常量不会触发此类的初始化

2.8为什么要自己定义类加载器,如何定义?
自定义类加载器的原因如下:
隔离加载类、修改类的加载方式、扩展加载源、防止源码泄露

自定义类加载器实现步骤:
1.可以通过继承抽象类javalangClassLoader类的方式,实现自己的类加载器,以满足一些特殊的需求
2.在JDK1.2之前,在自定义类加载器时,总会去继承ClassLoader类并重写loadClass()方法,从而实现自定义的类加载类,但是在JDK1.2之后已不再建议用户去覆盖loadClass()方法,而是建议把自定义的类加载逻辑写在findClass()方法中
3.在编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URLClassLoader类,这样就可以避免自己去编写findclass()方法及其获取字节码流的方式,使自定义类加载器编写更加简洁。

3字节码增强部分

3.1为何要学习字节码?
了解字节码可以准确且直观的理解java中更深层次的东西。因为在任何一种高级语言里面,我们解释一个程序如何运作都是跟两个方面是有关系的。第一个方面,就是本身语言的规范,这一点就是规范人的意识以及程序的意识,如同国家领导出台的文件。第二个方面&#

你可能感兴趣的:(JVM,java,面试,开发语言)