高级java开发工程师面试题之-----JVM篇

老规矩 先上图(不懂得先背图,图比源码好背多了)

1、JVM怎么加载class文件的

步骤如下

加载-》验证-》准备-》-识别-》初始化-》使用-》销毁,

加载:将各种数据源(可能是 class 文件、也可能是 jar 包,甚至网络)class字节码转化为二进制字节流(符合方法区域数据结构)加载到内存中并生成一个class对象

BootStrampClassLoader:加载JAVA_HOME下lib目录中的如rt.jar

ExtendClassLoader:加载JAVA_HOME下jre下所有的jar包或java-D

ApplicationClassLoader:加载在classpath中的我们自己写的文件

                       

验证:确保class文件字节流符合规范

准备:类静态变量分配内存并设置初始值 (附各种变量初始值表)

识别(也叫解析):解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,也就是得到类或者字段、方法在内存中的指针或者偏移量。

初始化:执行类的初始化方法,在准备阶段赋予了默认值,在此处会被赋予具体的值

总结:class通过类加载器被加载到内存中生成class对象,类加载器有三个分别是BootStrampClassLoader、ExtendClassLoader、ApplicationClassLoader、

加载过来之后就需要验证,比如修改了class文件,一个类继承了多个类,此时需要验证,验证、准备、识别之后,解析好生成运行时常量池ConstantPool,放入方法区或元空间。

静态变量在准备阶段被赋予默认值,在初始化阶段赋值

final常量在编译字节码是被生成了Constant属性,在准备阶段被赋值,所以final不会初始化

2、JVM内存结构

2.1 内存结构組成

 虚拟机栈:包括操作数栈、局部变量表(保存临时数据)、方法区或元数据方法的指针 

局部变量表:用于存储存放方法参数和局部变量,单位为变量槽,4个字节,32位,除了dubbo和long占两个变量槽,其他基本数据类型都占一个,引用类型可能占一个或两个

本地方法栈:与虚拟机栈的作用类似,区别是虚拟机栈执行的是java方法,而本地方法栈执行的是Nactive方法,即C++中的方法

方法区:存贮类的信息,常量、静态变量、即使编译器编译后的代码等数据,JDK1.8以后已经被元数据取代 (为什么被取代,因为分配内存时不知道给方法分配多大合适,大了造成浪费,小了容易OOM,干脆挪出去,用户内存有多少用多少)

执行引擎:

解释器:分为两种,一种是C++语言的解释java的字节码,另外一种是汇编语言的

执行编译器:对代码进行分析优化

GC:垃圾回收

面试话术:用来执行字节码,对字节码进行优化,然后执行GC,清理垃圾

3、垃圾回收机制GC

新生代存放朝生夕死的对象,因为朝生夕死,所以新生代留下的对象较少,因为对象较少,可以对这些对象进行复制,且不会产生内存碎片。

老年代由于对象存活比较久,且较大,所以不适合用复制算法,将对象来回拷贝,性能会非常低,所以使用的是单线程和多线程的整理算法,如标记清除,直接干掉。

这就是为什么老年代和新生代为什么要拆开,垃圾的性质不一样,回收的算法也不一样。

由于新生代用的是复制算法,那要复制到哪里去呢,所以新生代也分为了Eden、Survivor Space即From、To区,浪费了一点空间用于复制,From和To去交替使用。

4 面试题

4.1 双亲委派机制是什么?

(1)当加载一个类时,先判断此类是否已经被加载,如果类已经被加载则返回;

(2)如果类没有被加载,则先委托父类加载(父类加载时会判断该类有没有被自己加载过),如果父类加载过则返回;如果没被加载过则继续向上委托;

(3)如果一直委托都无法加载,子类加载器才会尝试自己加载。

4.2 为什么需要双亲委派机制?

(1) 通过双亲委派机制,可以避免类的重复加载,当父加载器已经加载过某一个类时,子加载器就不会再重新加载这个类。

(2) 通过双亲委派机制,可以保证安全性。因为BootstrapClassLoader在加载的时候,只会加载JAVA_HOME中的jar包里面的类,如java.lang.String,那么这个类是不会被随意替换的。

那么,就可以避免有人自定义一个有破坏功能的java.lang.String被加载。这样可以有效的防止核心Java API被篡改

4.3 怎么打破双亲委派机制?

打破双亲委派有两种方式:

第一种,自定义类加载器,必须重写findClass和loadClass;

第二种是通过线程上下文类加载器的传递性,让父类加载器中调用子类加载器的加载动作。

打破双亲委派机制并不是一件简单的事情,容易出现一些问题,比如类的重复加载、类的安全性等。因此,在实际开发中,我们应该慎重考虑是否需要打破双亲委派机制,并在实现时遵循一些规范和最佳实践。

4.4 static 代码块在类加载的哪一步执行的(美团面试题)

        初始化步骤执行

4.5垃圾回收算法都有哪些

标记-清理算法:标记要清除的对象 然后清除(产生内存碎片)

复制算法:把存活对象复制到另一个区域  然后清除区域(不产生内存碎片)

标记-整理:把存活对象压缩到内存的一段,然后清除边界线以外的区域(不产生内存碎片)

4.6 内存泄漏和内存溢出

内存溢出:申请内存但是内存不够了;

内存泄漏:申请内存后 不能释放已申请的内存空间;

4.7 JVM都有哪些垃圾回收器

单线程:新生代使用serial (简单高效) 老年代使用serial old 

多线程:新生代使用parNew (多核CPU比serial 表现好)老年代使用parOld

Parallele Scavenge: 新生代 并行 高吞吐量  适合后台应用等交互要求不高的场景

CMS:老年代 并行 牺牲吞吐量追求GC回收停顿最短时间

G1:一个region是标记清除算法 两个region之间是复制算法

4.7.1 JMM是什么?(内存模型)

        JMM控制了线程之间的通讯

       JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。

4.7.2 JVM内存屏障

        四种内存屏障如下:

         loadLoad: 保证 load1 的操作在load2之前执行

        loadStore: 保证在store写入操作之前 load已完成操作

        storeLoad:保证在操作之前 store已经刷新到内存

        storeStore:  保证在第二个store写操作之前 第一个store已经写入内存

        volatile通过内存屏障保证的可见性和有序性

4.7.3 JVM 垃圾回收器CMS 和G1的区别

       

        

        

持续更新中~~~~~~

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值