乐趣区

关于java:面试最常被问的-Java-后端题目及参考答案

一、Java 根底篇

  1. Object 有哪些罕用办法?大抵说一下每个办法的含意
  2. Java 创建对象有几种形式?
  3. 获取一个类对象的形式有哪些?
  4. ArrayList 和 LinkedList 的区别有哪些?
  5. 用过 ArrayList 吗?说一下它有什么特点?
  6. 有数组了为什么还要搞个 ArrayList 呢?
  7. 说说什么是 fail-fast?
  8. Hashtable 与 HashMap 的区别
  9. HashMap 中的 key 咱们能够应用任何类作为 key 吗?
  10. HashMap 的长度为什么是 2 的 N 次方呢?
  11. HashMap 与 ConcurrentHashMap 的异同
  12. 红黑树有哪几个特色?
  13. 说说你平时是怎么解决 Java 异样的
  14. finally 模块执行了吗?是先执行 return 还是先执行 finally 模块?返回什么?

二、JVM 篇

  1. Java 类加载器有几种?
  2. 说一下有哪些类加载场景?
  3. 说说 Java 类加载机制是什么?说说 new 创立一个一般对象的过程?
  4. 说说类的生命周期?
  5. 什么是双亲委派模型?
  6. 如何毁坏双亲委派模型?
  7. 能不能自己也写一个 java.lang.String 类?
  8. 说一下 JVM 运行时数据区有哪些?别离说一下它们的性能
  9. 办法区和永恒代有什么区别?
  10. JVM 运行时数据区哪些地方会产生内存溢出?
  11. 为什么要用 metaspace 替换 permspace 呢?
  12. 相熟哪些 JVM 调优参数?
  13. Java 对象的援用类型有哪些?
  14. JVM 垃圾回收算法有哪些?
  15. 垃圾收集器有哪些?
  16. 说说 JVM 中内存的调配与回收策略

三、Dubbo 篇

  1. 说说一次 Dubbo 服务申请流程?
  2. 说说 Dubbo 工作原理
  3. Dubbo 反对哪些协定?
  4. 注册核心挂了,consumer 还能不能调用 provider?
  5. 怎么实现动静感知服务下线的呢?
  6. Dubbo 负载平衡策略?
  7. Dubbo 容错策略
  8. Dubbo 动静代理策略有哪些?
  9. 说说 Dubbo 与 Spring Cloud 的区别?
  10. 说说 TCP 与 UDP 的区别,以及各自的优缺点
  11. 说一下 HTTP 和 HTTPS 的区别
  12. 说说 HTTP、TCP、Socket 的关系是什么?
  13. 说一下 HTTP 的长连贯与短连贯的区别

四、MyBatis 篇

  1. 说说 MyBatis 的缓存
  2. JDBC 编程有哪些步骤?
  3. 说一下 MyBatis 中应用的 #和 $ 有什么区别
  4. MyBatis 中比方 UserMapper.java 是接口,为什么没有实现类还能调用?
  5. MyBatis 中见过什么设计模式?

五、MySQL 篇

  1. 简略说说在 MySQL 中执行根据查问 SQL 是如何执行的?
  2. MySQL 有哪些存储引擎?
  3. MySQL 中 varchar 与 char 的区别?varchar(30) 中的 30 代表的涵义?
  4. int(11) 中的 11 代表什么涵义?
  5. 为什么 SELECT COUNT(*) FROM table 在 InnoDB 比 MyISAM 慢?
  6. 说说数据库的三范式和反模式
  7. 在设计数据库表的时候,字段用于存储金额、余额时,抉择什么类型比拟好?
  8. 大略说说 InnoDB 与 MyISAM 有什么区别?
  9. 什么是索引?
  10. 索引有什么优缺点?
  11. MySQL 索引类型有哪些?
  12. 什么时候不要应用索引?
  13. 应用 MySQL 的索引应该留神些什么?
  14. 怎么晓得一条查问语句是否用到了索引,用了什么类型的索引?
  15. 说说什么是 MVCC?
  16. MVCC 能够为数据库解决什么问题?
  17. 说说 MVCC 的实现原理
  18. 什么是死锁?
  19. MySQL 事务隔离级别?
  20. 请说说 MySQL 数据库的锁?
  21. 说说什么是锁降级?
  22. 说说乐观锁和乐观锁
  23. 怎么尽量避免死锁的呈现?

六、RabbitMQ 篇

  1. 看你简历上写了 RabbitMQ,通常会问:为什么要用 RabbitMQ?
  2. 可能你讲了下面三个 RabbitMQ 的长处后,会持续问:应用 RabbitMQ 容易带来什么问题?
  3. 那么多音讯队列,为什么选 RabbitMQ 呢?
  4. RabbitMQ 中什么是死信队列?
  5. 如何解决死信队列?
  6. 怎么保障音讯不会被失落?
  7. RabbitMQ 怎么高可用呢?
  8. RabbitMq 怎么保障音讯的程序性?
  9. 如果有大量音讯继续积压在队列了,怎么解决?

七、Redis 篇

  1. 为什么要用缓存
  2. 为什么 应用 Redis 而不是用 Memcached 呢?
  3. 为什么 Redis 单线程模型效率也能那么高?
  4. 说说 Redis 的线程模型
  5. 说一下 Redis 有什么长处和毛病
  6. Redis 缓存刷新策略有哪些?
  7. Redis 长久化形式有哪些?以及有什么区别?
  8. 长久化有两种,那应该怎么抉择呢?
  9. 怎么应用 Redis 实现音讯队列?
  10. 相熟哪些 Redis 集群模式?
  11. 缓存和数据库谁先更新呢?

八、Spring Boot 篇

  1. Spring Boot 提供了哪些外围性能?
  2. Spring Boot 外围注解是什么?
  3. 说说 Spring Boot 的主动拆卸原理
  4. Spring Boot 罕用 starter 有哪些?
  5. Spring 中的 starter 是什么?
  6. Spring Boot 有什么优缺点?
  7. 读取配置文件中配置项的有哪些办法?

九、Spring 篇

  1. Spring 中 ApplicationContext 和 BeanFactory 的区别
  2. 说一下你对 Spring IOC 的了解
  3. Spring IOC 有什么长处?
  4. Bean 的生命周期
  5. Spring Bean 的作用域有哪些?
  6. Spring 是怎么治理事务的?
  7. 说说你对 Spring AOP 的了解
  8. Spring 中用到了哪些设计模式?
  9. Spring 框架中的单例 Bean 是线程平安的么?
  10. Spring 是怎么解决循环依赖的?

十、ZooKeeper 篇

  1. 说说 ZooKeeper 是什么?
  2. ZooKeeper 有哪些利用场景?
  3. ZooKeeper 有哪些节点类型?
  4. 请形容一下 ZooKeeper 的告诉机制是什么?
  5. ZooKeeper 对节点的 watch 监听告诉是永恒的吗?
  6. ZooKeeper 集群中有哪些角色?
  7. ZooKeeper 集群中 Server 有哪些工作状态?
  8. ZooKeeper 集群中是怎么选举 leader 的?
  9. ZooKeeper 是如何保障事务的程序一致性的呢?
  10. ZooKeeper 集群中各服务器之间是怎么通信的?
  11. ZooKeeper 分布式锁怎么实现的?

十一、并发编程篇

  1. 通常创立线程有几种形式?
  2. 说说线程的生命周期
  3. 说说 synchronized 的应用和原理
  4. synchronized 和 ReentrantLock 区别
  5. 什么是线程平安?
  6. 线程平安须要保障几个基本特征
  7. 说一下线程之间是如何通信的?
  8. 说说你对 volatile 的了解
  9. 说一下 volatile 和 synchronized 的区别?
  10. Thread 调用 run 办法和调 start 办法的区别?
  11. 说一下 Java 创立线程池有哪些形式?
  12. 说说 ThreadLocal 底层原理是什么,怎么防止内存透露?
  13. 说说你对 JUC 下并发工具类
  14. CyclicBarrier 和 CountdownLatch 有什么区别?

十二、设计模式篇

  1. 你都相熟哪些设计模式

十三、其余篇

  1. 有 8 个球(大小色彩都截然不同),其中一个球比其余 7 个球中的任何一个都重,应用天平秤最多几次能找到最重的那个球?
  2. 分布式幂等性如何设计?
  3. 简略一次残缺的 HTTP 申请所经验的步骤?
  4. 说说分布式事务解决方案有哪些?
  5. 说说罕用的 JVM 调优命令和工具有哪些?
  6. 说说你对 JVM 内存溢出和内存透露的了解
  7. 说说 JVM 中有哪些罕用参数?

一、Java 根底篇

  1. Object 有哪些罕用办法?大抵说一下每个办法的含意
    java.lang.Object

上面是对应办法的含意。

clone 办法

爱护办法,实现对象的浅复制,只有实现了 Cloneable 接口才能够调用该办法,否则抛出

CloneNotSupportedException 异样,深拷贝也须要实现 Cloneable,同时其成员变量为援用类型的也须要实现 Cloneable,而后重写 clone 办法。

finalize 办法

该办法和垃圾收集器有关系,判断一个对象是否能够被回收的最初一步就是判断是否重写了此办法。

equals 办法

该办法应用频率十分高。个别 equals 和 == 是不一样的,然而在 Object 中两者是一样的。子类个别都要重写这个办法。

hashCode 办法

该办法用于哈希查找,重写了 equals 办法个别都要重写 hashCode 办法,这个办法在一些具备哈希性能的 Collection 中用到。

个别必须满足 obj1.equals(obj2)==true。能够推出 obj1.hashCode()==obj2.hashCode(),然而 hashCode 相等不肯定就满足 equals。不过为了提高效率,应该尽量使下面两个条件靠近等价。

JDK 1.6、1.7 默认是返回随机数;

JDK 1.8 默认是通过和以后线程无关的一个随机数 + 三个确定值,使用 Marsaglia’s xorshift scheme 随机数算法失去的一个随机数。

wait 办法

配合 synchronized 应用,wait 办法就是使以后线程期待该对象的锁,以后线程必须是该对象的拥有者,也就是具备该对象的锁。wait() 办法始终期待,直到取得锁或者被中断。wait(long timeout) 设定一个超时距离,如果在规定工夫内没有取得锁就返回。

调用该办法后以后线程进入睡眠状态,直到以下事件产生。

其余线程调用了该对象的 notify 办法;

其余线程调用了该对象的 notifyAll 办法;

其余线程调用了 interrupt 中断该线程;

工夫距离到了。

此时该线程就能够被调度了,如果是被中断的话就抛出一个 InterruptedException 异样。

notify 办法

配合 synchronized 应用,该办法唤醒在该对象上期待队列中的某个线程(同步队列中的线程是给抢占 CPU 的线程,期待队列中的线程指的是期待唤醒的线程)。

notifyAll 办法

配合 synchronized 应用,该办法唤醒在该对象上期待队列中的所有线程。

总结

只有把下面几个办法相熟就能够了,toString 和 getClass 办法能够不必去探讨它们。该题目考查的是对 Object 的相熟水平,平时用的很多办法并没看其定义然而也在用,比如说:wait() 办法,equals() 办法等。

Class Object is the root of the class hierarchy.Every class has Object as a superclass. All objects, including arrays, implement the methods of this class.

大抵意思:Object 是所有类的根,是所有类的父类,所有对象包含数组都实现了 Object 的办法。

面试扩散

下面提到了 wait、notify、notifyAll 办法,或者面试官会问你为什么 sleep 办法不属于 Object 的办法呢?因为提到 wait 等办法,所以最好把 synchronized 都说分明,把线程状态也都说分明,尝试让面试官跟着你的节奏走。

  1. Java 创建对象有几种形式?
    这题目看似简略,要好好答复起来还是有点小简单的,咱们来看看,到底有哪些形式能够创建对象?
  2. 应用 new 关键字,这也是咱们平时应用的最多的创建对象的形式,示例:

User user=new User();

  1. 反射形式创建对象,应用 newInstance(),然而得解决两个异样 InstantiationException、IllegalAccessException:

User user=User.class.newInstance();

Object object=(Object)Class.forName(“java.lang.Object”).newInstance()

3. 应用 clone 办法,后面题目中 clone 是 Object 的办法,所以所有对象都有这个办法。

4. 应用反序列化创建对象,调用 ObjectInputStream 类的 readObject() 办法。

咱们反序列化一个对象,JVM 会给咱们创立一个独自的对象。JVM 创建对象并不会调用任何构造函数。一个对象实现了 Serializable 接口,就能够把对象写入到文件中,并通过读取文件来创建对象。

总结

创建对象的形式关键字:new、反射、clone 拷贝、反序列化。

  1. 获取一个类对象的形式有哪些?
    搞清楚类对象和实例对象,但都是对象。

第一种:通过类对象的 getClass() 办法获取,仔细点的都晓得,这个 getClass 是 Object 类外面的办法。

User user=new User();

//clazz 就是一个 User 的类对象

Class<?> clazz=user.getClass();

第二种:通过类的动态成员示意,每个类都有隐含的动态成员 class。

//clazz 就是一个 User 的类对象

Class<?> clazz=User.class;

第三种:通过 Class 类的静态方法 forName() 办法获取。

Class<?> clazz = Class.forName(“com.tian.User”);

面试扩散

可能面试官会问相干的题目,比方:

Class.forName 和 ClassLoader.loadClass 的区别是什么?

参考:

反射中 Class.forName() 和 ClassLoader.loadClass() 的区别

  1. ArrayList 和 LinkedList 的区别有哪些?
    ArrayList

长处:ArrayList 是实现了基于动静数组的数据结构,因为地址间断,一旦数据存储好了,查问操作效率会比拟高(在内存里是连着放的)。

毛病:因为地址间断,ArrayList 要挪动数据,所以插入和删除操作效率比拟低。

LinkedList

长处:LinkedList 基于链表的数据结构,地址是任意的,所以在开拓内存空间的时候不须要等一个间断的地址。对于新增和删除操作,LinkedList 比拟占优势。LinkedList 实用于要头尾操作或插入指定地位的场景。

毛病:因为 LinkedList 要挪动指针,所以查问操作性能比拟低。

实用场景剖析

当须要对数据进行对随机拜访的时候,选用 ArrayList。

当须要对数据进行屡次减少删除批改时,采纳 LinkedList。

如果容量固定,并且只会增加到尾部,不会引起扩容,优先采纳 ArrayList。

当然,绝大数业务的场景下,应用 ArrayList 就够了,但须要留神防止 ArrayList 的扩容,以及非程序的插入。

  1. 用过 ArrayList 吗?说一下它有什么特点?
    只有是搞 Java 的必定都会答复“用过”。所以,答复题目的后半局部——ArrayList 的特点。能够从这几个方面去答复:

Java 汇合框架中的一种寄存雷同类型的元素数据,是一种变长的汇合类,基于定长数组实现,当退出数据达到肯定水平后,会履行主动扩容,即扩充数组大小。

底层是应用数组实现,增加元素。

如果 add(o),增加到的是数组的尾部,如果要减少的数据量很大,应该应用 ensureCapacity() 办法,该办法的作用是事后设置 ArrayList 的大小,这样能够大大提高初始化速度。

如果应用 add(int,o),增加到某个地位,那么可能会移动大量的数组元素,并且可能会触发扩容机制。

高并发的状况下,线程不平安。多个线程同时操作 ArrayList,会引发不可预知的异样或谬误。

ArrayList 实现了 Cloneable 接口,标识着它能够被复制。留神:ArrayList 外面的 clone() 复制其实是浅复制。

  1. 有数组了为什么还要搞个 ArrayList 呢?
    通常咱们在应用的时候,如果在不明确要插入多少数据的状况下,一般数组就很难堪了,因为你不晓得须要初始化数组大小为多少,而 ArrayList 能够应用默认的大小,当元素个数达到肯定水平后,会主动扩容。

能够这么来了解:咱们常说的数组是定死的数组,ArrayList 却是动静数组。

  1. 说说什么是 fail-fast?
    fail-fast 机制是 Java 汇合(Collection)中的一种谬误机制。当多个线程对同一个汇合的内容进行操作时,就可能会产生 fail-fast 事件。

例如:当某一个线程 A 通过 iterator 去遍历某汇合的过程中,若该汇合的内容被其余线程所扭转了,那么线程 A 拜访汇合时,就会抛出

ConcurrentModificationException 异样,产生 fail-fast 事件。这里的操作次要是指 add、remove 和 clear,对汇合元素个数进行批改。

解决办法:倡议应用“java.util.concurrent 包下的类”去取代“java.util 包下的类”。

能够这么了解:在遍历之前,把 modCount 记下来 expectModCount,前面 expectModCount 去和 modCount 进行比拟,如果不相等了,证实已并发了,被批改了,于是抛出

ConcurrentModificationException 异样。

  1. Hashtable 与 HashMap 的区别
    原本不想这么写题目的,然而无奈,面试官都喜爱这么问 HashMap。

出世的版本不一样,Hashtable 出生于 Java 公布的第一版本 JDK 1.0,HashMap 出生于 JDK 1.2。

都实现了 Map、Cloneable、Serializable(以后 JDK 版本 1.8)。

HashMap 继承的是 AbstractMap,并且 AbstractMap 也实现了 Map 接口。Hashtable 继承 Dictionary。

Hashtable 中大部分 public 润饰一般办法都是 synchronized 字段润饰的,是线程平安的,HashMap 是非线程平安的。

Hashtable 的 key 不能为 null,value 也不能为 null,这个能够从 Hashtable 源码中的 put 办法看到,判断如果 value 为 null 就间接抛出空指针异样,在 put 办法中计算 key 的 hash 值之前并没有判断 key 为 null 的状况,那阐明,这时候如果 key 为空,照样会抛出空指针异样。

HashMap 的 key 和 value 都能够为 null。在计算 hash 值的时候,有判断,如果 key==null,则其 hash=0;至于 value 是否为 null,基本没有判断过。

Hashtable 间接应用对象的 hash 值。hash 值是 JDK 依据对象的地址或者字符串或者数字算进去的 int 类型的数值。而后再应用除留余数法来取得最终的地位。然而除法运算是十分消耗工夫的,效率很低。HashMap 为了进步计算效率,将哈希表的大小固定为了 2 的幂,这样在取模估算时,不须要做除法,只须要做位运算。位运算比除法的效率要高很多。

Hashtable、HashMap 都应用了 Iterator。而因为历史起因,Hashtable 还应用了 Enumeration 的形式。

默认状况下,初始容量不同,Hashtable 的初始长度是 11,之后每次裁减容量变为之前的 2n+1(n 为上一次的长度)而 HashMap 的初始长度为 16,之后每次裁减变为原来的两倍。

另外在 Hashtable 源码正文中有这么一句话:

Hashtable is synchronized. If a thread-safe implementation is not needed, it is recommended to use HashMap in place of Hashtable . If a thread-safe highly-concurrent implementation is desired, then it is recommended to use ConcurrentHashMap in place of Hashtable.

大抵意思:Hashtable 是线程平安,举荐应用 HashMap 代替 Hashtable;如果须要线程平安高并发的话,举荐应用 ConcurrentHashMap 代替 Hashtable。

这个答复完了,面试官可能会持续问:HashMap 是线程不平安的,那么在须要线程平安的状况下还要思考性能,有什么解决形式?

这里最好的抉择就是 ConcurrentHashMap 了,但面试官必定会叫你持续说一下 ConcurrentHashMap 数据结构以及底层原理等。

  1. HashMap 中的 key 咱们能够应用任何类作为 key 吗?
    平时可能大家应用的最多的就是应用 String 作为 HashMap 的 key,然而当初咱们想应用某个自定义类作为 HashMap 的 key,那就须要留神以下几点:

如果类重写了 equals 办法,它也应该重写 hashCode 办法。

类的所有实例须要遵循与 equals 和 hashCode 相干的规定。

如果一个类没有应用 equals,你不应该在 hashCode 中应用它。

咱们自定义 key 类的最佳实际是使之为不可变的,这样,hashCode 值能够被缓存起来,领有更好的性能。不可变的类也能够确保 hashCode 和 equals 在将来不会扭转,这样就会解决与可变相干的问题了。

  1. HashMap 的长度为什么是 2 的 N 次方呢?
    为了能让 HashMap 存数据和取数据的效率高,尽可能地缩小 hash 值的碰撞,也就是说尽量把数据能平均的调配,每个链表或者红黑树长度尽量相等。

咱们首先可能会想到 % 取模的操作来实现。

上面是答复的重点哟:

取余(%)操作中如果除数是 2 的幂次,则等价于与其除数减一的与(&)操作(也就是说 hash % length == hash &(length – 1) 的前提是 length 是 2 的 n 次方)。并且,采纳二进制位操作 &,绝对于 % 可能进步运算效率。

这就是为什么 HashMap 的长度须要 2 的 N 次方了。

  1. HashMap 与 ConcurrentHashMap 的异同
    都是 key-value 模式的存储数据;

HashMap 是线程不平安的,ConcurrentHashMap 是 JUC 下的线程平安的;

HashMap 底层数据结构是数组 + 链表(JDK 1.8 之前)。JDK 1.8 之后是数组 + 链表 + 红黑树。当链表中元素个数达到 8 的时候,链表的查问速度不如红黑树快,链表会转为红黑树,红黑树查问速度快;

HashMap 初始数组大小为 16(默认),当呈现扩容的时候,以 0.75 * 数组大小的形式进行扩容;

ConcurrentHashMap 在 JDK 1.8 之前是采纳分段锁来事实的 Segment + HashEntry,Segment 数组大小默认是 16,2 的 n 次方;JDK 1.8 之后,采纳 Node + CAS + Synchronized 来保障并发平安进行实现。

  1. 红黑树有哪几个特色?
    紧接上个问题,面试官很有可能会问红黑树,上面把红黑树的几个特色列出来:

如果面试官还要持续问红黑树具体是怎么增加节点和删除节点的,举荐看:

30 张图带你彻底了解红黑树

  1. 说说你平时是怎么解决 Java 异样的
    try-catch-finally

try 块负责监控可能出现异常的代码

catch 块负责捕捉可能呈现的异样,并进行解决

finally 块负责清理各种资源,不论是否出现异常都会执行

其中 try 块是必须的,catch 和 finally 至多存在一个规范异样解决流程

抛出异样→捕捉异样→捕捉胜利(当 catch 的异样类型与抛出的异样类型匹配时,捕捉胜利)→异样被解决,程序持续运行 抛出异样→捕捉异样→捕捉失败(当 catch 的异样类型与抛出异样类型不匹配时,捕捉失败)→异样未被解决,程序中断运行

在开发过程中会应用到自定义异样,在通常状况下,程序很少会本人抛出异样,因为异样的类名通常也蕴含了该异样的有用信息,所以在抉择抛出异样的时候,应该抉择适合的异样类,从而能够明确地形容该异常情况,所以这时候往往都是自定义异样。

自定义异样通常是通过继承 java.lang.Exception 类,如果想自定义 Runtime 异样的话,能够继承

java.lang.RuntimeException 类,实现一个无参结构和一个带字符串参数的有参构造方法。

在业务代码里,能够针对性的应用自定义异样。比如说:该用户不具备某某权限、余额有余等。

  1. finally 模块执行了吗?是先执行 return 还是先执行 finally 模块?返回什么?
    public class FinallyDemo {
    public String method111() {
    String ret = “hello”;
    try {
    return ret;
    } finally {
    ret = “world”;
    }
    }
    }
    把 FinallyDemo.java 编译成 class 文件后,找到该 class 文件的当前目录,执行 cmd 命令:

javap -verbose FinallyDemo.class >>test.txt

而后关上 test.txt,要害局部内容如下:

发现在字节码指令中,将 hello 保留在本地变量 2 中,而后直到把本地变量 2 加载到操作数栈中,而后就间接出栈,return 回去了,所以本题的返回去的是 hello,然而 finally 代码块也执行了,执行完 finally 模块后再返回一个长期变量 2。

二、JVM 篇

  1. Java 类加载器有几种?
  2. 说一下有哪些类加载场景?
  3. 说说 Java 类加载机制是什么?说说 new 创立一个一般对象的过程?
    类加载的过程包含了:

加载、验证、筹备、解析、初始化。

new 创立一个一般对象的过程如下:

检测类是否被加载过

为对象分配内存

为调配的内存空间初始化为 0

对对象进行其余相干设置

执行 init 办法

上面用一张图来形容:

  1. 说说类的生命周期?
    留神类生命周期和对象申明周期,类生命周期次要有以下几个阶段:
  2. 什么是双亲委派模型?
  3. 如何毁坏双亲委派模型?
  4. 能不能自己也写一个 java.lang.String 类?
    能够写,能编译,然而不能 run。禁止应用包名:java. 结尾的包名。

定义一个一般类:

package java.lang;

public class MyTest {

public MyTest() {
}
public MyTest(String str, int a) {
}

public int length(){
return 10;
}
public static void main(String[] args) {
MyTest myTest =new MyTest(“lang”,1);
myTest.length();
}
}
运行:

具体校验的源码中央:

论断就是定义包目录的时候,不能以 java. 结尾。

  1. 说一下 JVM 运行时数据区有哪些?别离说一下它们的性能
    此题我想用我的办法说,不像网上一堆一堆抄书上的,心愿能对大家有所帮忙,如果没多大帮忙,那能够网上找个看看,只能说道歉了。

上面咱们直入主题:

每个线程独自领有的:程序计数器、Java 虚拟机栈、本地办法栈

所有线程都独特有的:办法区、堆

如果你在 Java 代码里创立一个线程,相应 JVM 虚拟机中就创立与之对应的程序计数器、Java 虚拟机栈、本地办法栈,同时办法区和堆是在虚拟机启动就曾经有了。

程序计数器

能够简略了解为:程序计数器是记录执行到你代码的的第几行了,每个线程各自对应本人的程序计数器。

Java 虚拟机栈

虚构机会为每个线程调配一个虚拟机栈,每个虚拟机栈中都有若干个栈帧,每个栈帧中存储了局部变量表、操作数栈、动静链接、返回地址等。一个栈帧就对应 Java 代码中的一个办法,当线程执行到一个办法时,就代表这个办法对应的栈帧曾经进入虚拟机栈并且处于栈顶的地位,每一个 Java 办法从被调用到执行完结,就对应了一个栈帧从入栈到出栈的过程。一个线程的生命周期和与之对应的 Java 虚拟机栈的生命周期雷同。

一个线程进来就创立虚拟机栈,该线程调用的办法就是栈帧,进入办法,栈帧就入栈(虚拟机栈),出办法就是出虚拟机栈。能够通过上面两张图进行了解:

本地办法栈

和 Java 虚拟机栈相似,Java 虚拟机栈针对的是 Java 办法,而本地办法栈针对的 native 润饰的办法。

JVM 简直所有的对象的内存调配都在堆里。因为对象是有生命周期的,所以把堆又分成了新生代和老年代。

新生代和老年代大小比例 = 1:2(默认)。新生代又分为 Eden、S0、S1 区域,Ede:S0:S1=8:1:1。

大多数对象在 Eden 区出世和死亡。Eden 区存活下来的对象进入 S0 区,S0 区活下来的对象放到 S1,S1 区活下来的对象放到 S0 区,这过程中 S0 和 S1 至多有一个区域是空着的。并且对象每次倒腾一次本人的年龄就加 1,中转加到 15 岁的时候,就间接入老年代了。有的大对象能够间接进入老年代,条件是把该对象的大小以及达到了能间接进入老年代的条件了(阈值能够设置)。

办法区

先依照图中的关键字答复。然而办法区因为 JDK 版本有所变动。

答复的时候,肯定要说一下办法区因为 JDK 版本有所变动。版本变动状况如下:

  1. 办法区和永恒代有什么区别?
    之前有小伙伴也问过我,办法区和永恒代到底是什么区别?

这么说吧:永恒代又叫 Perm 区,只存在于 HotSpot JVM 中,并且只存在于 JDK 1.7 和之前的版本中,JDK 1.8 中曾经彻底移除了永恒代,JDK 1.8 中引入了一个新的内存区域叫 metaspace。

并不是所有的 JVM 中都有永恒代,IBM 的 9,Oracle 的 JRocket 都没有永恒代。

永恒代是实现层面的货色。

永恒代外面存的货色基本上就是办法区规定的那些货色。

因而,咱们能够说,在 JDK 1.7 中永恒代是办法区的一种实现,当然,在 HotSpot JDK 1.8 中 metaspace 能够看成是办法区的一种实现。

  1. JVM 运行时数据区哪些地方会产生内存溢出?
    简略答复就行:

Java 虚拟机栈、本地办法栈、Java 堆、办法区,其实就是除了程序计数器以外的几个都会产生 OOM。

倡议把阈值对应的几个区也简要的说一下:

  1. 为什么要用 metaspace 替换 permspace 呢?
    在 JDK 1.8 之前的 HotSpot 实现中,类的元数据如办法数据、办法信息(字节码、栈和变量大小)、运行时常量池、已确定的符号援用和虚办法表等被保留在永恒代中,32 位默认永恒代的大小为 64M,64 位默认为 85M,能够通过参数 -XX:MaxPermSize 进行设置,一旦类的元数据超过了永恒代大小,就会抛出 OOM 异样。

虚拟机团队在 JDK 1.8 的 HotSpot 中,把永恒代从 Java 堆中移除了,并把类的元数据间接保留在本地内存区域(堆外内存),称之为元空间 metaspace(本地内存)。即就是说 JDK 1.8 之前,永恒代是在虚拟机中的,而 JDK 1.8 引入的元空间是零碎的内存的一部分。实践上取决于 32 位 /64 位零碎可虚构的内存大小,可见也不是无限度的,须要配置参数。

另外一方面,咱们在对永恒代进行调优的时候是相当吃力,因为永恒代的大小不好管制,波及到很多因素,比方:类的总数、常量池的大小、办法数量等,最无语的是永恒代的内存不够了可能会随同着一次 Full GC。

上面是 JDK 几个版本中办法区和堆存储的信息的关系:

总结

字符串存在永恒代中,容易呈现性能问题和内存溢出。

类及办法的信息等比拟难确定其大小,因而对于永恒代的大小指定比拟艰难,太小容易呈现永恒代溢出,太大则容易导致老年代溢出。

永恒代会为 GC 带来不必要的复杂度,并且回收效率偏低。

移除永恒代是为交融 HotSpot JVM 与 JRockit VM 而做出的致力,因为 JRockit 没有永恒代,不须要配置永恒代。

  1. 相熟哪些 JVM 调优参数?
    整个堆内存大小

-Xms(初始堆大小)、-Xmx(最大堆大小),为了避免垃圾收集器在最小、最大之间膨胀堆而产生额定的工夫,咱们通常把最大、最小设置为雷同的值。

新生代空间大小

NewRadio:年老代和年轻代将依据默认的比例(1:2)调配堆内存,倡议设置为 2 到 4,能够通过调整二者之间的比率 NewRadio 来调整二者之间的大小。也能够针对回收代,比方年老代,通过 -XX:newSize -XX:MaxNewSize 来设置其相对大小。同样,为了避免年老代的堆膨胀,咱们通常会把 -XX:newSize -XX:MaxNewSize 设置一样大小。

办法区(元空间)

JDK 1.8:-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m,依据理论状况调整,能够应用命令 jstat -gcutil pid 查看以后使用率,M 对应的列,依据使用率来定制一个具体的值,倡议两个值设置成同样大小。

JDK 1.7:-XX:MaxPermSize=256m -XX:MaxPermSize=256m 永恒带。

GC 日志

-Xloggc:$CATALINA_BASE/logs/gc.log

-XX:+PrintGCDetails

-XX:+PrintGCDateStamps

记录 GC 日志并不会特地地影响 Java 程序性能,举荐你尽可能记录日志。

GC 算法

-XX:+UseParNewGC

-XX:+CMSParallelRemarkEnabled

-XX:+UseConcMarkSweepGC

-XX:CMSInitiatingOccupancyFraction=75

一般来说举荐应用这些配置,然而依据程序不同的个性,其余的也有可能更好。

任何一个 JVM 参数的默认值能够通过

java -XX:+PrintFlagsFinal -version |grep JVMParamName

获取,例如:

java -XX:+PrintFlagsFinal -version |grep MetaspaceSize

  1. Java 对象的援用类型有哪些?
    对象援用类型有四类:强援用、软援用、弱援用、虚援用。
  2. JVM 垃圾回收算法有哪些?
    垃圾回收算法共四种:其实我更违心说成三种,因为分代回收其实不是算法。
  3. 垃圾收集器有哪些?
    目前常见的有如下几种:

Serial 收集器

ParNew 收集器

Parallel scavenge 收集器

Serial Old 收集器

CMS=Concurrent Mark Sweep 收集器

Parallel Old 收集器

G1=Garbage-First 收集器

垃圾收集器整合

G1 是新生代和老年代一起搞,不和他人合伙。

Serial:CMS 或者 Serial Old

ParNew:CMS 或者 Serial Old

Parallel Scavenge:Parallel Old 或者 Serial Old

分代收集器对应

新生代收集器:Serial、ParNew、Parallel Scavenge

老年代收集器:Serial Old、Parallel Old、CMS

整堆收集器:G1

  1. 说说 JVM 中内存的调配与回收策略
    三、Dubbo 篇
    其实对于 Dubbo 的面试题,我感觉最好的文档应该还是官网,因为官网有中文版,关照了很多浏览英文文档吃力的小伙伴。然而官网内容挺多的,于是这里就联合官网和平时面试被问的绝对较多的题目整顿了一下。
  2. 说说一次 Dubbo 服务申请流程?
    根本工作流程:

上图中角色阐明:

  1. 说说 Dubbo 工作原理
    工作原理分 10 层:

第一层:service 层,接口层,给服务提供者和消费者来实现的(留给开发人员来实现);

第二层:config 层,配置层,次要是对 Dubbo 进行各种配置的,Dubbo 相干配置;

第三层:proxy 层,服务代理层,通明生成客户端的 stub 和服务单的 skeleton,调用的是接口,实现类没有,所以得生成代理,代理之间再进行网络通讯、负责平衡等;

第四层:registry 层,服务注册层,负责服务的注册与发现;

第五层:cluster 层,集群层,封装多个服务提供者的路由以及负载平衡,将多个实例组合成一个服务;

第六层:monitor 层,监控层,对 rpc 接口的调用次数和调用工夫进行监控;

第七层:protocol 层,近程调用层,封装 rpc 调用;

第八层:exchange 层,信息替换层,封装申请响应模式,同步转异步;

第九层:transport 层,网络传输层,形象 mina 和 netty 为对立接口;

第十层:serialize 层,数据序列化层。

这是个很坑爹的面试题,然而很多面试官又喜爱问,你真的要背么?你能背那还是不错的,我倡议不要背,你就想想 Dubbo 服务调用过程中应该会波及到哪些技术,把这些技术串起来就 OK 了。

面试扩散

如果让你设计一个 RPC 框架,你会怎么做?其实你就把下面这个工作原理中波及的到技术点总结一下就行了。

  1. Dubbo 反对哪些协定?
    还有三种,混个眼生就行:Memcached 协定、Redis 协定、Rest 协定。

上图基本上把序列化的形式也列举进去了。

具体请参考:Dubbo 官网。

  1. 注册核心挂了,consumer 还能不能调用 provider?
    能够。因为刚开始初始化的时候,consumer 会将须要的所有提供者的地址等信息拉取到本地缓存,所以注册核心挂了能够持续通信。然而 provider 挂了,那就没法调用了。

关键字:consumer 本地缓存服务列表。

  1. 怎么实现动静感知服务下线的呢?
    服务订阅通常有 pull 和 push 两种形式:

pull 模式须要客户端定时向注册核心拉取配置;

push 模式采纳注册核心被动推送数据给客户端。

Dubbo ZooKeeper 注册核心采纳是事件告诉与客户端拉取形式。服务第一次订阅的时候将会拉取对应目录下全量数据,而后在订阅的节点注册一个 watcher。一旦目录节点下产生任何数据变动,ZooKeeper 将会通过 watcher 告诉客户端。客户端接到告诉,将会从新拉取该目录下全量数据,并从新注册 watcher。利用这个模式,Dubbo 服务就能够做到服务的动静发现。

留神:ZooKeeper 提供了“心跳检测”性能,它会定时向各个服务提供者发送一个申请(实际上建设的是一个 socket 长连贯),如果长期没有响应,服务中心就认为该服务提供者曾经“挂了”,并将其剔除。

  1. Dubbo 负载平衡策略?
    随机(默认):随机来

轮训:一个一个来

活跃度:机器活跃度来负载

一致性 hash:落到同一台机器上

  1. Dubbo 容错策略
    failover cluster 模式

provider 宕机重试当前,申请会分到其余的 provider 上,默认两次,能够手动设置重试次数,倡议把写操作重试次数设置成 0。

failback 模式

失败主动复原会在调用失败后,返回一个空后果给服务消费者。并通过定时工作对失败的调用进行重试,适宜执行音讯告诉等操作。

failfast cluster 模式

疾速失败只会进行一次调用,失败后立刻抛出异样。实用于幂等操作、写操作,相似于 failover cluster 模式中重试次数设置为 0 的状况。

failsafe cluster 模式

失败平安是指,当调用过程中出现异常时,仅会打印异样,而不会抛出异样。实用于写入审计日志等操作。

forking cluster 模式

并行调用多个服务器,只有一个胜利即返回。通常用于实时性要求较高的读操作,但须要节约更多服务资源。可通过 forks=”2″ 来设置最大并行数。

broadcacst cluster 模式

播送调用所有提供者,一一调用,任意一台报错则报错。通常用于告诉所有提供者更新缓存或日志等本地资源信息。

  1. Dubbo 动静代理策略有哪些?
    默认应用 javassist 动静字节码生成,创立代理类,然而能够通过 SPI 扩大机制配置本人的动静代理策略。
  2. 说说 Dubbo 与 Spring Cloud 的区别?
    这是很多面试官喜爱问的问题,自己认为其实他们没什么关联之处,然而硬是要问区别,那就说说吧。

答复的时候次要围绕着四个关键点来说:通信形式、注册核心、监控、断路器,其余像 Spring 分布式配置、服务网关必定得晓得。

通信形式

Dubbo 应用的是 RPC 通信;Spring Cloud 应用的是 HTTP RestFul 形式。

注册核心

Dubbo 应用 ZooKeeper(官网举荐),还有 Redis、Multicast、Simple 注册核心,但不举荐。;

Spring Cloud 应用的是 Spring Cloud Netflix Eureka。

监控

Dubbo 应用的是 Dubbo-monitor;Spring Cloud 应用的是 Spring Boot admin。

断路器

Dubbo 在断路器这方面还不欠缺,Spring Cloud 应用的是 Spring Cloud Netflix Hystrix。

分布式配置、网关服务、服务跟踪、音讯总线、批量工作等。

Dubbo 目前能够说还是空白,而 Spring Cloud 都有相应的组件来撑持。

  1. 说说 TCP 与 UDP 的区别,以及各自的优缺点
  2. 说一下 HTTP 和 HTTPS 的区别
    端口不同:HTTP 和 HTTPS 的连贯形式不同没用的端口也不一样,HTTP 是 80,HTTPS 用的是 443;

耗费资源:和 HTTP 相比,HTTPS 通信会因为加解密的解决耗费更多的 CPU 和内存资源;

开销:HTTPS 通信须要证书,这类证书通常须要向认证机构申请或者付费购买。

  1. 说说 HTTP、TCP、Socket 的关系是什么?
    TCP/IP 代表传输控制协议 / 网际协议,指的是一系列协定族。

HTTP 自身就是一个协定,是从 Web 服务器传输超文本到本地浏览器的传送协定。

Socket 是 TCP/IP 网络的 API,其实就是一个门面模式,它把简单的 TCP/IP 协定族暗藏在 Socket 接口前面。对用户来说,一组简略的接口就是全副,让 Socket 去组织数据,以合乎指定的协定。

综上所述:

须要 IP 协定来连贯网络。

TCP 是一种容许咱们平安传输数据的机制,应用 TCP 协定来传输数据的 HTTP 是 Web 服务器和客户端应用的非凡协定。

HTTP 基于 TCP 协定,所以能够应用 Socket 去建设一个 TCP 连贯。

  1. 说一下 HTTP 的长连贯与短连贯的区别
    HTTP 协定的长连贯和短连贯,本质上是 TCP 协定的长连贯和短连贯。

短连贯

在 HTTP/1.0 中默认应用短链接,也就是说,浏览器和服务器每进行一次 HTTP 操作,就建设一次连贯,但工作完结就中断连贯。如果客户端拜访的某个 HTML 或其余类型的 Web 资源,如 JavaScript 文件、图像文件、CSS 文件等。当浏览器每遇到这样一个 Web 资源,就会建设一个 HTTP 会话。

长连贯

从 HTTP/1.1 起,默认应用长连贯,用以放弃连贯个性。在应用长连贯的状况下,当一个网页关上实现后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连贯不会敞开。如果客户端再次拜访这个服务器上的网页,会持续应用这一条曾经建设的连贯。Keep-Alive 不会永恒放弃连贯,它有一个放弃工夫,能够在不同的服务器软件(如 Apache)中设定这个工夫。

四、MyBatis 篇

  1. 说说 MyBatis 的缓存
    一级缓存

在利用运行过程中,咱们有可能在一次数据库会话中,执行屡次查问条件完全相同的 SQL,MyBatis 提供了一级缓存的计划优化这部分场景,如果是雷同的 SQL 语句,会优先命中一级缓存,防止间接对数据库进行查问,进步性能。

每个 SqlSession 中持有了 Executor,每个 Executor 中有一个 LocalCache。当用户发动查问时,MyBatis 依据以后执行的语句生成 MappedStatement,在 Local Cache 进行查问,如果缓存命中的话,间接返回后果给用户,如果缓存没有命中的话,查询数据库,后果写入 Local Cache,最初返回后果给用户。具体实现类的类关系图如下图所示:

MyBatis 一级缓存的生命周期和 SqlSession 统一。

MyBatis 一级缓存外部设计简略,只是一个没有容量限定的 HashMap,在缓存的功能性上有所欠缺。

MyBatis 的一级缓存最大范畴是 SqlSession 外部,有多个 SqlSession 或者分布式的环境下,数据库写操作会引起脏数据,倡议设定缓存级别为 Statement。

二级缓存

在上文中提到的一级缓存中,其最大的共享范畴就是一个 SqlSession 外部,如果多个 SqlSession 之间须要共享缓存,则须要应用到二级缓存。开启二级缓存后,会应用 CachingExecutor 装璜 Executor,进入一级缓存的查问流程前,先在 CachingExecutor 进行二级缓存的查问,具体的工作流程如下所示。

二级缓存开启后,同一个 namespace 下的所有操作语句,都影响着同一个 Cache,即二级缓存被多个 SqlSession 共享,是一个全局的变量。

当开启缓存后,数据的查问执行的流程为:

二级缓存 -> 一级缓存 -> 数据库

MyBatis 的二级缓存绝对于一级缓存来说,实现了 SqlSession 之间缓存数据的共享,同时粒度更加细,可能到 namespace 级别,通过 Cache 接口实现类不同的组合,对 Cache 的可控性也更强。

MyBatis 在多表查问时,极大可能会呈现脏数据,有设计上的缺点,平安应用二级缓存的条件比拟刻薄。

在分布式环境下,因为默认的 MyBatis Cache 实现都是基于本地的,分布式环境下必然会呈现读取到脏数据,须要应用集中式缓存将 MyBatis 的 Cache 接口实现,有肯定的开发成本,间接应用 Redis、Memcached 等分布式缓存可能老本更低,安全性也更高。

  1. JDBC 编程有哪些步骤?
  2. 装载相应的数据库的 JDBC 驱动并进行初始化:

Class.forName(“com.mysql.jdbc.Driver”);

  1. 建设 JDBC 和数据库之间的 Connection 连贯:

Connection c = DriverManager.getConnection(“jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8”, “root”, “123456”);

  1. 创立 Statement 或者 PreparedStatement 接口,执行 SQL 语句:

// 查问用户信息
public List<User> findUserList(){
String sql = “select * from t_user order by user_id”;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
// 创立一个 List 用于寄存查问到的 User 对象
List<User> userList = new ArrayList<>();
try {
conn = DbUtil.getConnection();
pstmt =(PreparedStatement) conn.prepareStatement(sql);
rs =(ResultSet) pstmt.executeQuery();
while(rs.next()){
int courseId = rs.getInt(“user_id”);
String courseName = rs.getString(“user_name”);
// 每个记录对应一个 User 对象
User user = new User();
user.setUserId(courseId);
user.setUserName(courseName);
// 将对象放到汇合中
userList.add(course);
}
} catch(SQLException e) {
e.printStackTrace();
}finally{
// 资源敞开
DbUtil.close(pstmt);
DbUtil.close(conn);
}
return userList;
}

  1. 解决和显示后果。
  2. 开释资源。
  3. 说一下 MyBatis 中应用的 #和 $ 有什么区别
    动静 SQL 是 MyBatis 的次要个性之一,在 mapper 中定义的参数传到 xml 中之后,在查问之前 MyBatis 会对其进行动静解析。

MyBatis 为咱们提供了两种反对动静 SQL 的语法:#{} 以及 ${}。

{} 是预编译解决,${} 是字符替换。在应用 #{} 时,MyBatis 会将 SQL 中的 #{} 替换成 ?,配合 PreparedStatement 的 set 办法赋值,这样能够无效的避免 SQL 注入,保障程序的运行平安。

倡议能不要用就不要用,“常在河边走哪能不湿鞋”。

  1. MyBatis 中比方 UserMapper.java 是接口,为什么没有实现类还能调用?
    UserMapper.xml 中:

<mapper namespace=”com.tian.UserMapper”>

反射生成 namespace 的对象:

boundType = Resources.classForName(namespace);

JDK 动静代理:

Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);

总结:XML 中的 namespace=”com.user.UserMapper” 接口 com.user.UserMapper 自身反射 JDK 动静代理实现接口。

  1. MyBatis 中见过什么设计模式?
    五、MySQL 篇
  2. 简略说说在 MySQL 中执行根据查问 SQL 是如何执行的?
    select name from t_user where id=1

获得链接,应用应用到 MySQL 中的连接器。

查问缓存,key 为 SQL 语句,value 为查问后果,如果查到就间接返回。不倡议应用次缓存,在 MySQL 8.0 版本曾经将查问缓存删除,也就是说 MySQL 8.0 版本后不存在此性能。

分析器,分为词法剖析和语法分析。此阶段只是做一些 SQL 解析,语法校验。所以个别语法错误在此阶段。

优化器,是在表里有多个索引的时候,决定应用哪个索引;或者一个语句中存在多表关联的时候(join),决定各个表的连贯程序。

执行器,通过分析器让 SQL 晓得你要干啥,通过优化器晓得该怎么做,于是开始执行语句。执行语句的时候还要判断是否具备此权限,没有权限就间接返回提醒没有权限的谬误;有权限则关上表,依据表的引擎定义,去应用这个引擎提供的接口,获取这个表的第一行,判断 id 是都等于 1。如果是,间接返回;如果不是持续调用引擎接口去下一行,反复雷同的判断,直到取到这个表的最初一行,最初返回。

MySQL 的典型的三层构造(连接器 + Server + 执行器):

  1. MySQL 有哪些存储引擎?

能够说这一篇(宝典),熟知本文 80% 以上内容,找个开发工作问题不大。对 3 - 5 年教训的敌人,也是疾速复习的利器!本次的内容大抵的就介绍到这里啦,因为内容太多,只能简略介绍到这里,如有须要以上内容的完整版,大家能够私信我获取哦~~ 后盾关注我后私信回复:【666】即可获取

退出移动版