工做三年终于社招进字节跳动!字节跳动,阿里,腾讯Java岗面试经验汇总

前言

我大概我是从去年12月份开始看书学习,到今年的6月份,一直学到看你们的面经基本上百分之90以上都会,我就在5月份开始投简历,边面试边补充基础知识等。也是有些辛苦。终因而在前不久拿到了字节跳动的offer,如今我也来写面经,但愿能帮助到你们!前端

面经

Java基础

0.HashMap的源码,实现原理,JDK8中对HashMap作了怎样的优化。java

拉链结构,数组+链表,原理是hash找数组,冲突后拉链表,1.8优化为会进化成红黑树提升效率,而且使用2^n来作容量值面试

引伸点:redis

  • equal & hashcode算法

  • 其余地方的hash处理,如redis的hash、集群slot等sql

  • 对hash算法类型的了解(安全哈希和非安全哈希如mermerhash)数据库

  • 对hashMap实现的了解:取hashcode,高位运算,低位取模设计模式

  • 一致性hash(处理了什么问题,在什么场景用到)数组

  • 红黑树简单描述

1.HaspMap扩容是怎样扩容的,为何都是2的N次幂的大小。缓存

在容量到达抵达负载因子*最大容量的时候进行扩容,负载因子的默认值为0.75

2N的缘由:

  • hash的计算是经过hashcode高低位混合而后和容量的length进行与运算

  • 在length=2n的时候,与运算至关因而一个取模操做

  • 那么在每次rehash完毕以后mod2N的意义在于要么该元素是在原位置,要么是在最高位偏移多一位的位置,提升效率

引伸点:

  • ConcurrentHashMap的扩容:1.7分段扩容以及1.8transfer并发协同的扩容

  • redis渐进式hash扩容处理

3.HashMap,HashTable,ConcurrentHashMap的区别。

Map线程不安全(没有用任何同步相关的原语),Table安全(直接加syn),Concurrent提供更高并发度的安全(分段锁思想orSyn+Cas)

引伸点:

  • 对线程安全的定义:如hashmap在1.7前会头插死循环,可是在1.8改善后仍是不能叫线程安全,由于没有可见性

  • 对锁粒度的思考:在介于map和table之间存在tradeoff以后的均衡解

  • Syn和ReentranceLock的区别

  • 锁升级

4.极高并发下HashTable和ConcurrentHashMap哪一个性能更好,为何,如何实现的。

分两种状况讨论:

  1. 极高并发读:并发读的状况下,Table也为读加了锁,没有并发可言,ConcurrentMap读锁并无加并发,直接可读,若读resize的某个tab为空则转到新tab去读,Node的元素val和指针next都是volatile修饰的,能够保证可见性,因此concurrentMap获胜

  2. 极高并发写:在并发写的状况下,table也是直接加了Syn作锁,强制串行,而且resize也只能单线程扩容,ConcurrentMap首先对于每一个数组都有并发度,其次在resize的时候支持多线程协同,因此concurrentMap获胜

因此总体而言concurrentMap优点在于:

  1. 读操做基于volatile可见性因此无锁

  2. 写操做优点在于一是粗粒度的数组锁,二是协同resize

这个问题的思路是先分类讨论而后描述细节最后在下结论

引伸点:

  • volatile的实现:保证内存可见、禁止指令重排序但没法保证原子性

  • java内存模型

  • JVM作的并行优化、先行发生原则与指令重排序

  • 底层细节的熟悉

5.HashMap在高并发下若是没有处理线程安全会有怎样的安全隐患,具体表现是什么。

1.7前死锁,1.7后线程会获取脏值致使逻辑不可靠

6.java中四种修饰符的限制范围。

public:公用,谁来了都给你用

protected:包内使用,子类也可以使用

default:包内使用,子类不可以使用

private:本身用

7.Object类中的方法。

wait\hashcode\equal\wait\notify\getclass\tostring\nofityall\finalize

引伸点:

  • wait和sleep区别

  • hashcode存在哪儿(对象头里)

  • finalize做用:GC前执行,可是不必定能把这个函数跑完

  • getClass后能获取什么信息:引伸到反射

8.接口和抽象类的区别,注意JDK8的接口能够有实现。

接口:能够imp多个接口,1.7以前不容许实现,1.8后能够实现方法

抽象类:只能继承一个类,抽象类中能够存在默认实现方法

接口的语义是继承该接口的类有该类接口的行为

抽象类的语义是继承该抽象类的类自己就是该抽象类

9.动态代理的两种方式,以及区别。

  1. CGLIB:其本质是在内存中继承了一个子类,能够代理但愿代理的那个类的全部方法

  2. JDK动态代理:实现InvocationHandler,经过生成一个Proxy来反射调用全部的接口方法

优劣:

  • CGLIB:会在内存中多存额外的class信息,对metaspace区的使用有影响,可是性能好,能够访问非接口的方法

  • JDK动态代理:本质是生成一个继承全部接口的Proxy来反射调用方法,局限性在于其只能代理接口的方法

引伸点:

  • Spring的AOP实现以及应用场景

  • 反射的开销:检查方法权限,序列化以及匹配入参

  • ASM

10.Java序列化的方式。

继承Serializable接口并添加SerializableId(idea有组件能够直接生成),ID其实是一个版本,标志着序列化的结构是否相同

11.传值和传引用的区别,Java是怎么样的,有没有传值引用。

本质上来说Java传递的是引用的副本,实际上就是值传递,可是这个值是引用的副本,好比方法A中传入了一个引用ref,那么在其中将ref指向其余对象并不影响在方法A外的ref,由于ref在传入方法A的时候其实是指向同一个对象的另外一个引用,能够称之为ref',ref'若直接修改引用的对象会影响ref,但若ref'指向其余对象则和ref没有关系了

12.一个ArrayList在循环过程当中删除,会不会出问题,为何。

分状况讨论:

  1. fori删除,不会直接抛异常,可是会产生异常访问

  2. foreach删除(实际就是迭代器),会直接抛出并发修改异常,由于迭代器会进行获取迭代器时的exceptModCount和真实的modCount的对比

引伸点:

  • 迭代器实现

  • ArrayList内部细节

13.@transactional注解在什么状况下会失效,为何。

方法A存在该注解,同时被方法B调用,外界调用的是Class.B的方法,由于内部实际上的this.a的调用方式没走代理类因此不会被切面切到

数据结构和算法

1.B+树

出度为m的一颗树,节点的子女在[M/2,M]之间

叶子节点存储全量信息

非叶子节点只充当索引进行叶子节点的路由(内存友好、局部性友好)

底层的叶子节点以链表的形式进行相连(范围查找友好)

2.快速排序,堆排序,插入排序(其实八大排序算法都应该了解

快排:核心是分治logn

堆排:基于二叉树nlogn

插入:暴力n2

3.一致性Hash算法,一致性Hash算法的应用

一致性hash,将整个hash的输出空间当成一个环,环中设立多个节点,每一个节点有值,当对象的映射知足上个节点和这个节点中间值的时候它就落到这个节点当中来

应用:redis缓存,好处是平滑的数据迁移和快速的rebalance

引伸点:

  • 一致性hash热点怎么处理:虚拟节点

  • redis如何实现的:客户端寻址

JVM

1.JVM的内存结构。

程序计数器:计算读到第几行了,相似一个游标

方法栈:提供JVM方法执行的栈空间

本地方法栈:提供native方法执行的栈空间

堆:存对象用的,young分eden,s0,s1,分配比例大概是8:1:1,Old只有一个区

方法区:1.8后为metaspace,存class信息,常量池(后迁移到堆中),编译出来的热点代码等

引伸点:

  • heap何时发生溢出

  • stack何时发生溢出
  • 方法区何时发生溢出
  • hotspot code的机制
  • 流量黑洞如何产生的

2.JVM方法栈的工做过程,方法栈和本地方法栈有什么区别。

方法栈是JVM方法使用的,本地方法栈是native方法使用的,在hotspot实际上是用一个

3.JVM的栈中引用如何和堆中的对象产生关联。

引用保存地址,直接能够查找到堆上对应地址的对象

4.能够了解一下逃逸分析技术。

方法中开出来的local变量若是在方法体外不存在的话则称之为没法逃逸

  • 能够直接分配在栈上,随着栈弹出直接销毁,省GC开销

  • 消除全部同步代码,由于本质上就是个单线程执行

引伸点:

JVM编译优化:

  • 逃逸分析

  • 栈上分配

  • 分层编译与预热

  • 栈上替换

  • 常量传播

  • 方法内联

    ...

5.GC的常见算法,CMS以及G1的垃圾回收过程,CMS的各个阶段哪两个是Stop the world的,CMS会不会产生碎片,G1的优点。

常见算法:

  1. 标记清楚:存在内存碎片,下降内存使用效率

  2. 标记整理:整理可分为复制整理和原地整理,不存在内存碎片,可是须要额外的cpu算力来进行整理,若为复制算法还须要额外的内存空间

CMS流程:

  1. 初始标记(stw):得到老年代中跟GCRoot以及新生代关联的对象,将其标记为root

  2. 并发标记:将root标记的对象所关联的对象进行标记

  3. 重标记:在并发标记阶段,并无stw,因此会有一些脏对象产生,即标记完毕以后又产生关联对象修改

  4. 最终标记(stw):最终肯定全部没有脏对象的存活对象

  5. 并发清理:并发的清理全部死亡对象

  6. Reset:重设程序为下一次FGC作准备

CMS优劣:

  • 优势:

    • 不像PN以及Serial同样全程须要stw,只须要在两个标记阶段stw便可

    • 并发标记、清楚来提高效率,减小stw的时间和总体gc时间

    • 在最终标记前经过预设次数的重标记来清理脏页减小stw时间
  • 缺点:

    • 仍然存在stw

    • 基于标记清楚算法的GC,节省算力可是会产生内存碎片

    • 并发标记和清楚会形成cpu的高负担

G1流程:

这个我只懂个大概,以下

分块分代回收,可分为youngGC和MixedGC,特色是可预测的GC时间(即所谓的软实时特性)

引伸点:

  • 是否进行过线上分析

  • GC日志是否读过,里面有什么信息

  • 大家应用的YGC和FGC频率以及时间是多少

  • 你清楚当前应用YGC最多的通常是什么吗

业务相关:

  • 在线上大部分curd业务当中,实际上形成ygc影响较严重且可优化的是日志系统

  • 对dump出来的堆进行分析的话里面有很大一块是String,而其中大几率会是日志中的各类入参出参

  • 优化方案有不少:

    • 将不须要打日志的地方去除全量日志打印功能

    • 日志在不一样环境分级打印

    • 只打出错误状态的日志

    • 在大促期间关闭非主要日志打印

    • 同步改异步等

6.标记清除和标记整理算法的理解以及优缺点。

上文已答

7.eden survivor区的比例,为何是这个比例,eden survivor的工做过程。

8:2

定性的来说:大部分对象都只有极短的存活时间,基本就是函数run到尾就释放了,因此给新晋对象的buffer须要占较多的比例,而s区能够相对小一点来容纳长时间存活的对象,较小的另外一个缘由是在几回年龄增加后对象会进入老年代

定量的来说:实验所得,也能够根据本身服务器的状况动态调整(不过笔者没调过)

8.JVM如何判断一个对象是否该被GC,能够视为root的都有哪几种类型。

没有被GCRoot所关联

Root对象:(tips:不用硬记,针对着JVM内存区域来理解便可)

  1. 函数栈上的引用:包括虚拟机栈和native栈

  2. static类的引用:存在方法区内

  3. 常量池中的常量:堆中

引伸点:

  • gc roots和ref count的区别

9.强软弱虚引用的区别以及GC对他们执行怎样的操做。

强:代码中正常的引用,存在即不会被回收

软:在内存不足的时候会对其进行GC,可用于缓存场景(相似redis淘汰)

弱:当一个对象只有弱引用关联的时候会被下一次GC给回收

虚:又称幽灵引用,基本没啥用,在GC的时候会感知到

引伸点:

  • 每一个引用的使用场景

  • 是否在源码或者项目中看到过or使用过这几种引用类型(ThreadLocal里用了WeakReference)

10.Java是否能够GC直接内存。

在GC过程当中若是发现堆外内存的Ref被使用则GC

11.Java类加载的过程。

12.双亲委派模型的过程以及优点。

13.经常使用的JVM调优参数。

14.dump文件的分析。

15.Java有没有主动触发GC的方式(没有)。

多线程

1.Java实现多线程有哪几种方式。

2.Callable和Future的了解。

3.线程池的参数有哪些,在线程池建立一个线程的过程。

4.volitile关键字的做用,原理。

5.synchronized关键字的用法,优缺点。

6.Lock接口有哪些实现类,使用场景是什么。

7.可重入锁的用处及实现原理,写时复制的过程,读写锁,分段锁(ConcurrentHashMap中的segment)

8.悲观锁,乐观锁,优缺点,CAS有什么缺陷,该如何解决。

9.ABC三个线程如何保证顺序执行。

10.线程的状态都有哪些。

11.sleep和wait的区别。

12.notify和notifyall的区别。

13.ThreadLocal的了解,实现原理。

数据库相关

1.常见的数据库优化手段

  1. log同步刷盘改异步刷盘

  2. 集群的话强双写改异步同步

  3. 针对sql优化(explain慢sql)

  4. 添加索引

2.索引的优缺点,什么字段上创建索引

优势:查的快,支持range

缺点:大部分查询实际须要回表,索引创建会额外消耗内存和磁盘,对开发者的sql也有要求

字段:区分度大的字段

3.数据库链接池。

4.durid的经常使用配置。

计算机网络

1.TCP,UDP区别。

2.三次握手,四次挥手,为何要四次挥手。

3.长链接和短链接。

4.链接池适合长链接仍是短链接。

设计模式

1.观察者模式

2.代理模式

举例子JDK动态代理,经过一层proxy对真实对象进行代理,进行一些额外操做(e.g.:加强行为、负载均衡等)

3.单例模式,有五种写法,能够参考文章单例模式的五种实现方式

  1. 普通单例

  2. lazyloading+syn单例

  3. lazyloading+doublecheck单例

  4. 枚举

  5. 最后一种不知道,查了发现是静态内部类单例,利用静态内部类第一次访问才加载的机制实现lazyloading

4.能够考Spring中使用了哪些设计模式

分布式相关

1.分布式事务的控制。

2.分布式锁如何设计。

3.分布式session如何设计。

4.dubbo的组件有哪些,各有什么做用。

duboo不熟悉

5.zookeeper的负载均衡算法有哪些。

zookeeper就会个zab,不过负载均衡无非是公平轮询、加权轮询、随机轮询或者维护某些资源信息的动态路由这几种

6.dubbo是如何利用接口就能够通讯的。

不太熟,估计涉及到服务注册以及序列化反序列化相关内容

缓存相关

1.redis和memcached的区别。

2.redis支持哪些数据结构。

3.redis是单线程的么,全部的工做都是单线程么。

4.redis如何存储一个String的。

5.redis的部署方式,主从,集群。

6.redis的哨兵模式,一个key值如何在redis集群中找到存储在哪里。

7.redis持久化策略。

框架相关

1.SpringMVC的Controller是如何将参数和前端传来的数据一一对应的。

2.Mybatis如何找到指定的Mapper的,如何完成查询的。

3.Quartz是如何完成定时任务的。

4.自定义注解的实现。

5.Spring使用了哪些设计模式。

6.Spring的IOC有什么优点。

7.Spring如何维护它拥有的bean。

一些较新的东西

1.JDK8的新特性,流的概念及优点,为何有这种优点。

2.区块链了解

3.如何设计双11交易总额面板,要作到高并发高可用。

最后

但愿我总结的这些东西对大家会有帮助,大家看完以后有什么的不懂的欢迎在下方留言讨论,也能够私信问我,我通常看完以后都会回的,也能够关注个人公众号:前程有光,立刻金九银十跳槽面试季,整理了1000多道将近500多页pdf文档的Java面试题资料,文章都会在里面更新,整理的资料也会放在里面。

相关文章
相关标签/搜索