现在JDK都14了,但是很多人可能连JDK 8 新特性都没玩过,那面试的时候如何高效地和面试官瞎扯蛋呢?那自然是需要题库(题库)啦! 考虑到这一点,小编决定,将市面上设计比较多的
做任何大事,都需要从最细微的小事开始,所以前面几天的文章会先从基础开始, 可能大部分人都觉得相对简单,不过也能查漏补缺,不放过任何细节。
举一个小栗子,我们就以现在面试过程中,被问到最多的jvm中的GC,先来看一下下面的这些面试题
Java 提供的GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的, Java 语言没有提供释放已分配内存的显式操作方法。 在堆中,找到已经无用的对象,并把这些对象占用的空间收回使其可以重新利用。 要请求垃圾收集,可以调用下面的方法之一:
算法思路:把所有的对象组成一个集合,或者可以理解为树状结构,从树根开始找,只要可以找到的都是活动对象,如果找不到就应该被回收了。
内存运行时 JVM 会有一个运行时数据区来管理内存。它主要包括 5 大部分:
而其中程序计数器、虚拟机栈、本地方法栈是每个线程私有的内存空间,随线程而生,随线程而亡。例如栈中每一个栈帧中分配多少内存基本上在类结构确定是哪个时就已知了,因此这 3 个区域的内存分配和回收都是确定的,无需考虑内存回收的问题。 但方法区和堆就不同了,一个接口的多个实现类需要的内存可能不一样,我们只有在程序运行期间才会知道会创建哪些对象,这部分内存的分配和回收都是动态的,GC 主要关注的是这部分内存。
总结:GC 主要进行回收的内存是 JVM 中的方法区和堆
标记-清除算法(Mark-Sweep) 从根节点开始标记所有可达对象,其余没有标记的即为垃圾对象,执行清除。但回收后的空间是不连续的。标记-清除算法采用从根集合进行扫描,对存活的对象标记,标记完毕后,在扫描整个空间中未被标记的对象,进行回收。 标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片。
复制算法 复制算法采用从根集合扫描,并将存活对象复制到一块新的,没有使用过的空间中,这种算法当控件存活的对象比较少时,极为高效,但是带来的成本是需要一块内存交换空间进行对象的移动。也就是s0,s1等空间。
标记-整理法 标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时,在回收不存活的对象占用的空间后,会将所有的存活对象网左端空闲空间移动,并更新相应的指针。标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题。
对于堆中的对象,用可达性分析判断一个对象是否还存在引用,如果该对象没有任何引用就应该被回收。根据实际对引用的不同需求,分成了 4 种引用,每种引用的回收机制也是不同的。 对于方法区中的常量和类,当一个常量没有任何对象引用它,它就可以被回收了。 对于类,如果可以判定它为无用类,就可以被回收了。
判断一个对象是否存活有两种方法: 1. 引用计数法 所谓引用计数法就是给每一个对象设置一个引用计数器,每当有一个地方引用这个对象 时,就将计数器加一,引用失效时,计数器就减一。当一个对象的引用计数器为零时,说 明此对象没有被引用,也就是“死对象”,将会被垃圾回收. 引用计数法有一个缺陷就是无法解决循环引用问题,也就是说当对象 A 引用对象 B,对象 B 又引用者对象 A,那么此时 A,B 对象的引用计数器都不为零,也就造成无法完成垃圾回 收,所以主流的虚拟机都没有采用这种算法。
2.可达性算法(引用链法) 该算法的思想是:从一个被称为 GC Roots 的对象开始向下搜索,如果一个对象到 GC Roots 没有任何引用链相连时,则说明此对象不可用。 在 java 中可以作为 GC Roots 的对象有以下几种:
虽然这些算法可以判定一个对象是否能被回收,但是当满足上述条件时,一个对象比不一定会被回收。 当一个对象不可达 GC Root 时,这个对象并不会立马被回收,而是出于一个死缓的阶段,若要被真正的回收需要经历两次标记: 如果对象在可达性分析中没有与 GC Root 的引用链,那么此时就会被第一次标记并且进行一次筛选,筛选的条件是是否有必要执行 finalize()方法。当对象没有覆盖 finalize()方法或者已被虚拟机调用过,那么就认为是没必要的。 如果该对象有必要执行 finalize()方法,那么这个对象将会放在一个称为 F-Queue 的对队列中,虚拟机会触发一个 Finalize()线程去执行,此线程是低优先级的,并且虚拟机不会承诺一直等待它运行完,这是因为如果 finalize()执行缓慢或者发生了死锁,那么就会造成 F-Queue 队列一直等待,造成了内存回收系统的崩溃。GC 对处于 F-Queue 中的对象进行第二次被标记,这时,该对象将被移除”即将回收”集合,等待回收。
静态分派 所有依赖静态类型来定位方法执行版本的分派动作称为静态分派,其典型应用是方法重载(根据参数的静态类型来定位目标方法)。 静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机执行的。
动态分派 在运行期根据实际类型确定方法执行版本。
怎么样,这只是一个GC,而由GC也可以引出来一系列的问题:jvm--->性能调优--->mysql调优--->负载均衡--->设计模式--->。。。。毕竟技术之间的连贯性还是相当强的,所以整理面试题,从面试出发,根据公司面试的业务需求进行整理,有针对性会帮助你节省不少的时间,就像是大学考试之前划重点一样,我也将相应的知识点和来自阿里、字节的朋友一起整理成了一张思维导图
除了每一个知识点可以点开查看之外
我们也尽自己最大的能力,将内容进行整理和改进,形成了xmind格式的思维导图,但是毕竟这是我们整理的,不一定能满足所有人的
篇幅原因,就不一一详细展示了,看一下xmind自己记录的打开记录吧,需要这份资料的,关注+转发后,私信“资料”即可查看获取方式
为了能够让大家更好的学习,我们也将相应的问题整理,录制了一系列的视频资料,讲解相应的知识点问题,并且上传网盘进行保存
有需要的朋友,同样的获取方式,关注+转发后,私信“资料”‘即可查看获取方式
最后当然是最重磅的面试题
话不多说,直接放上面试题截图
有需要的朋友,同样的获取方式,关注+转发后,私信“资料”‘即可查看获取方式