面经四五六

1、Spring 原理、Spring IOC、AOP

说一下Bean 如何加载、如何初始化以及如何注册到IOC容器中的详细过程, 涉及BeanDefinition、BeanFactory也深入细节聊一下。

2、一个请求过来在Spring中发生了哪些事情?

这个问题不妨把一个请求过来在TCP层面上建立连接、操作系统如何处理连接、Web容器接收到连接对象后做了哪些事情、Spring 如何对接收到的请求进行处理都说一下,当然最终还是落在Spring 容器内部如何处理一个请求,这个过程一定要说清楚,需要体现细节。

3、手写一个栈,实现 push,pop方法,以及 max(获取最大的元素) 方法,要求时间复杂度为 O(1)

4、JVM内存结构

需要你能画出JVM内存结构的图,画出方法区、堆、程序计算器、虚拟机栈、本地方法栈,并说出每一个部分具体是什么作用,比如,哪些是线程共享的,哪些是线程独享的,哪些地方存放了什么数据,为什么会这样存放,哪些虚拟机参数对这些空间大小是有影响的,可以如何配置。这些都比较常规。

5、手写一个基于懒汉式的双重检测的单例。

(1)单例有三个比较关键的点,一是私有构造方法,避免外部new出对象;二是保证唯一性;三是提供一个全局访问点。

(2)另外,懒汉式双重检测的实现方式 有三点需要注意的地方,一是全局访问点必须是静态的,外界使用可以通过类直接调用,二是在进入锁之后还需要校验,三是保存单例对象的私有变量一定要用volatile修饰,这个地方可以多说一些,比如volatile防止指令重排序,保证内存可见性(JVM层面和CPU层面可以分别说)。

6、HashMap相关

(1)在jdk1.8之后,HashMap除了数组+链表之外,引用了红黑树。需要说明对于引用了红黑树的 HashMap 如何put一个元素,以及链表是在何时转化为红黑树的。比如,首先需要知道这个元素落在哪一个数组里,获取hashcode后并不是对数组长度取余来确定的,而是高低位异或求与来得到的。这个地方首先得知道异或求与是做什么样的运算的。

(2)之后说一下在HashMap中的实现,比如hashcode无符号右移16位后和原hashcode做异或运算,这相当于把hashcode的高16位拿过来和hashcode的低16位做异或运算,因为无符号右移后前面说的16位都补零,这就是前面说的"高低位异或“,进而是“求与”,和谁求与呢,和数组长度减1 求与。说到这里起码能够证明你是看过源码的,接下来说说你的思考,比如我们知道对于hashmap 初始化容量决定了数组大小,一般我们对于数组这个初始容量的设置是有规律的,它应该是 2^n 。这个初始容量的设置影响了HashMap的效率,那又涉及到影响HashMap效率的主要因素,比如初始容量和负载因子。

7、为什么要引入红黑树?

8、如何在红黑树中插入一个节点。

9、链表是如何转换为红黑树的?

10、对ConcurrentHashMap的理解,⽐如在什么地⽅会涉及到线程安全问题以及ConcurrentHashMap是如何解决的?

11、JVM四种引入类型

这个问题比较简单,强引入、弱引入、软引入、虚引入,说一下它们各自的特点和GC对它们的不同处理方式,再说一下常用的应用场景或者jdk的实现中对它们的使用,比如,ThreadLocal 的静态内部类ThreadLocalMap,它的Key是弱引用的,也可以说一下 在你的理解中 为什么它是弱引用的,假如不是会怎么样。

1.(强引用)通过new指令创建出来的对象都属于强引用类型,堆中的对象与栈中的变量保持着直接引用。保持强引用的对象是不会被GC机制回收的

2.(弱引用)当一个对象只存在软引用时,在堆内存不足的情况下,该引用级别的对象将被GC机制回收。不过当堆内存还充足的情况下,该引用级别的对象是不会被回收的,所以平时如果需要实现JVM级别的简单缓存,那么可以使用该级别的引用类型实现。使用案例如下

SoftReference<HashMap> cacheSoftRef = 
    new SoftReference<HashMap>(new HashMap<Object,Object>());
cacheSoftRef.get().put("竹子","熊猫");
System.out.println(cacheSoftRef.get().get("竹子"));

3.(软引用)从软引和弱引的特性上来看,它们都适合用来实现简单的缓存机制,用于保存那些可有可无的缓存数据,内存充足时可以稍微增加程序的执行效率,而内存紧张时会被回收,不会因此导致OOM。

4.与其他的几种引用类型不同的是:虚引用不会决定GC机制对一个对象的回收权,如果一个对象仅仅存在虚引用,那么GC机制将会把他当成一个没有任何引用类型的对象,随时随刻可以回收它。不过它还有个额外的用途:跟踪垃圾回收过程,也正是由于虚引用可以跟踪对象的回收时间,所以也可以将一些资源释放操作放置在虚引用中执行和记录。

因为key如果不设计成弱引用类型的情况下,会造成entry中value出现内存泄漏的场景

首先key=null的情况,会发生在内存不足的时候,由于Key是弱引用类型的,所以会被强制回收,回收之后自然key就成了null。

我相信你的意思是指,既然key被设计成了弱引用,所以才会导致key=null的情况出现,那假设把key设计成强引用,是不是就解决了这个问题呢?先看个例子:
public static void main(String[] args) {
ThreadLocal TL = new ThreadLocal();
TL.set(new Object());
TL = null;
}
这里创建了一个ThreadLocal对象TL,并设置一个Object对象,然后将其置空。如果Key不是弱引用的话,TL无法被回收,也无法被访问,Object无法被回收,也无法被访问,Key和Value同时出现了内存泄漏。

为啥K-V都内存泄漏了呢?因为最后一行置空代码,只能将main线程栈中的引用置空,而Thread对象内部有一个threadLocals成员,依旧会保持与ThreadLocalMap的引用,而Map的Key又强引用自ThreadLocal,这时main线程的栈,虽然没有引用这个TL,但Map却在引用着它,最终就导致了K-V都内存泄漏。

上面也是ThreadLocalMap中,为什么Key被设计成弱引用的原因,而且ThreadLocal也在尽可能的避免内存泄漏,当你调用set/get/remove()方法时,都会清理过期的Key(调用remove方法是最有效的)

变量ThreadLocal是非static的就会造成每次生成实例都要生成不同的ThreadLocal对象,虽然这样程序不会有什么异常,但是会浪费内存资源.造成内存泄漏.

12、SpringBoot 启动过程

这个主要是从它基于Spring的事件发布和监听机制开始说起

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值