Java基础
1.JDK和JRE有什么区别?
- JDK 是java development kit的简称,java开发工具包,提供java的开发环境和运行环境。
- JRE 是java runtime environment 的简称,java运行环境,为java的运行提供了所需的环境。
- JDK其中包含了JRE,同时还包含了编译java源码的编译器javac,还包含了不少程序调试和分析的工具。简单来讲若是你须要运行程序只须要安装JRE就能够,可是若是须要编写程序要安装JDK。
2.==和equal的区别?
基本数据类型:比较的是值是否相等。
引用数据类型:比较的是引用是否相等。
- equal:至关于==,默认状况下是引用比较不过有些如String,integer重写了equal方法,把它改为值比较。
3.两个对象的hashcode相同,则equals方法必定为TRUE,对吗?
- 不对,由于在散列表中,hashcode相等即两个键值对的哈希值相等,然而哈希值相等,键值对不必定相等。
4.final在java中有什么做用?
- final修饰类该类叫最终类,不能被继承。
- final修饰方法,改方法不能被重写。
- final修饰变量,变量为常量,必须初始化,且不能改变。
5.java中 round(-1.5)等于多少?
- 等于-1,round方法对值加0.5。即在数轴上向右取整。
6.string属于基本数据类型吗?
- 不属于,基本数据类型有八种:int,char,long,byte,float,boolean,double,short。
7.java中操做字符串都有哪些类?它们之间的区别是什么
- 操做字符串的类有:string,stringbuilder,stringbuffer。
- string和二者的区别是,string声明 的是不可变对象,每次操做都会生成新的对象,而后把指针指向新的对象,另外两个能够以原有对象的基础上进行操做,因此常常改变字符串就不要使用string。
- Stringbuffer和Stringbuilder最大的区别在于Stringbuffer是线程安全的,Stringbuilder不是线程安全的,可是Stringbuilder的性能却高于Stringbuffer,因此在单线程环境下推荐使用Stringbuilder,多线程状况下使用Stringbuffer。
8.String str=“i”和String str=new String(“i”)同样吗
- 不同,第一种java虚拟机会在常量池分配空间,第二种是在堆内存中分配空间。
9.如何将字符串反转?
- 使用Stringbuffer和Stringbuilder的reverse()方法。
10.String类的经常使用方法有哪些?
- indexof():返回指定字符的索引。
- chatAt:返回指定索引处的字符。
- replase:字符串替换。
- trim:去除字符串两边空白。
- split:分割字符串,返回分割后的字符串数组。
- getByte:返回字符串的byte类型数组。
- length:返回字符串长度。
- toLowerCase:将字符型改为小写字母。
- toUperCase:将字符串改为大写字母。
- subString:截取字符串。
- equals:字符串比较。
11.抽象类必需要有抽象方法吗?
12.普通类和抽象类有什么区别?
- 普通类不能包括抽象方法,抽象类能够有抽象方法。
- 普通类能够直接实例化,抽象类不能直接实例化。
13.抽象类能够用final修饰吗?
- 不能,定义抽象类就是为了让别的类继承的,而final修饰的类不能被继承,因此相互矛盾。
14.接口和抽象类有什么不一样?
- 实现:抽象类的子类必须使用extends来继承父类,接口使用implement来实现接口。
- 构造函数:抽象类中能够有构造方法,接口中不能有构造方法。
- 访问修饰符:接口中的方法默认的访问修饰符是public,抽象类中方法任何访问修饰符均可以。
- 实现数量:一个类能够实现不少个接口,但只能继承一个一个抽象类。
15.java中IO流分为几种?
- 按功能分类:输入流(input)、输出流(output)。
- 按类型来分:字节流、字符流。
- 字节流按8位传输以字节为单位输入输出数据。字符流按16为传输以字符为单位传入传出数据。
16.BIO、NIO、AIO有什么区别?
- BIO是block io 同步阻塞式io,是咱们日常使用的传统io,它的特色是模式简单易用,并发处理能力低。
- NIO是 new io 同步非阻塞式io,是传统io的升级,客户端和服务端经过Channel通信,实现多路复用。
- AIO是 Asynchronous io是NIO的升级,也叫NIO2,实现异步非阻塞io,异步io的操做基于事件和回调机制。
17.Files类的方法有哪些?
- Files.exist():检测文件路径是否存在。
- Files.createFiles():建立文件。
- Files.createDirectory():建立文件目录。
- Files.delete():删除文件或目录。
- Files.copy():复制文件。
- Files.move():移动文件。
- Files.size():查看文件个数。
- FIles.read():读取文件。
- Files.write():写入文件。
容器
1.Java容器有哪些?
- java 容器分为collection和map两大类 其中又有不少子类。
- Collection
- List
- ArrayList
- LinkedList
- Vector
- Stack
- Set
- HashSet
- LinkedHashSet
- TreeSet
- Map
- HashMap
- TreeMap
- ConcurrentHashMap
- Hashtable
2.Collection和Collections有什么区别?
- Collection是一个集合接口,它提供了对集合对象进行操做的通用接口方法,全部集合都是它的子类,好比List、Set等。
- Collections是一个包装类,包含不少静态方法,不能被实例化,就像一个工具类,好比提供的排序方法 Collections.sort(list).
3.List、Set、Map三者之间的区别?
- 三者主要区别体如今两方面:元素是否有序、是否容许元素重复。
- 不一样以下图:
4.HashMap和Hashtable有什么区别?
- 存储:HashMap运行的key和values能够为null,Hashtable不容许。
- 线程安全:Hashtable是线程安全,HashMap是非线程安全的。
- 推荐使用:在Hashtable的类注释能够看到,Hashtable是保留类不建议使用,推荐在单线程下使用HashMap替代,若是须要多线程使用则使用ConcurrentHashMap。
5.如何决定使用HashMap仍是TreeMap?
- 对于在Map中插入、删除、定位一个元素时,使用HashMap会更好,由于HashMap插入会更快。但若是要对key集合进行有序遍历,选择TreeMap会比较好。
6.说一下HashMap的实现原理。
- HashMap是基于hash算法实现的,咱们经过put(key,value)来存储元素,get(key)获取。当key传入时,HashMap会根据key.hashCode()计算hash值,根据hash值将value存放在bucket里。当计算的hash值相同时,咱们称之为hash冲突,HashMap的作法是用链表和红黑树存储相同的hash值的value。当hash冲突个数比较少时,使用链表不然使用红黑树。
7.说一下HashSet的实现原理。
- HashSet是基于HashMap实现的,HashSet底层是使用HashMap来保存全部数据的,所以HashSet的实现原理比较简单,相关的Hashset操做,基本上都是直接调用底层HashMap实现的,Hashset不容许值重复。
8.ArrayList和LinkedList的区别是什么?
- 存储结构:ArrayList是动态数组的数据结构实现,LinkedList是双向链式的数据结构。
- 随机访问效率:ArrayList比LinkedList效率高,由于LinkedList是线性的数据存储方式,全部须要移动指针从前日后依次查找。
- 增长和删除效率:在非首尾增长或删除数据元素,LinkedList效率比较高,由于ArrayLiat增删要影响到数组内其余数据的下标。
- 总的来讲,频繁读取数据使用arrylist,增删操做则使用Linkedlist
9.如何实现数组和List之间的转换?
- 数组转List:使用ArryList.asList(array)进行转换。
- List转数组:使用List自带的toArray()方法。
10.ArrayLiat和Vector的区别?
- 线程安全:Vector使用了Synchronized来实现线程同步,是线程安全的,而ArrayList是非线程安全的。
- 性能:arraylist性能比vector高。
- 扩容:ArrayList 和 Vector 都会根据实际的须要动态的调整容量,只不过在 Vector 扩容每次会增长 1 倍,而 ArrayList 只会增长 50%。
11.Array和ArrayList有什么区别?
- Array 能够存储基本数据类型和对象,ArrayList 只能存储对象。
- Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。
- Array 内置方法没有 ArrayList 多,好比 addAll、removeAll、iteration 等方法只有 ArrayList 有。
12.在Queue中poll()和remove()有什么区别?
- 相同点:都是返回第一个元素,并在队列中删除返回的对象。
- 不一样点:若是没有元素 poll()会返回 null,而 remove()会直接抛出NoSuchElementException 异常。
13.哪些集合类时线程安全的?
- Vector、Hashtable、Stack 都是线程安全的,而像 HashMap 则是非线程安全的,不过在 JDK 1.5 以后随着 Java. util. concurrent 并发包的出现,它们也有了本身对应的线程安全类,好比 HashMap 对应的线程安全类就是 ConcurrentHashMap。
14.迭代器iterator是什么?
- Iterator 接口提供遍历任何 Collection 的接口。咱们能够从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器容许调用者在迭代过程当中移除元素。
15.Iterator 怎么使用?有什么特色?
- Iterator 的特色是更加安全,由于它能够确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。
16.Iterator 和 ListIterator 有什么区别?
- Iterator 能够遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。
- Iterator 只能单向遍历,而 ListIterator 能够双向遍历(向前/后遍历)。
- ListIterator 从 Iterator 接口继承,而后添加了一些额外的功能,好比添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
17.怎么确保一个集合不能被修改?
- 可使用 Collections. unmodifiableCollection(Collection c) 方法来建立一个只读集合,这样改变集合的任何操做都会抛出 Java. lang. UnsupportedOperationException 异常。
多线程
1.并行和并发有什么区别?
- 并行:多个处理器或多核处理器同时处理多个任务。
- 并发:多个任务在同一个 CPU 核上,按细分的时间片轮流(交替)执行,从逻辑上来看那些任务是同时执行。
- 并发 = 两个队列和一台咖啡机。
- 并行 = 两个队列和两台咖啡机。
2.线程和进程的区别?
- 一个程序下至少有一个进程,一个进程下至少有一个线程,一个进程下也能够有多个线程来增长程序的执行速度。
3.守护线程是什么?
- 守护线程是运行在后台的一种特殊进程。它独立于控制终端而且周期性地执行某种任务或等待处理某些发生的事件。在 Java 中垃圾回收线程就是特殊的守护线程。
4.建立线程有哪几种方式?
- 建立线程有三种方式:
- 继承 Thread 重写 run 方法;
- 实现 Runnable 接口;
- 实现 Callable 接口。
5.说一下 runnable 和 callable 有什么区别?
- runnable 没有返回值,callable 能够拿到有返回值,callable 能够看做是 runnable 的补充。
6.线程有哪些状态?
- RUNNABLE 正在执行中
- BLOCKED 阻塞的(被同步锁或者IO锁阻塞)
- WAITING 永久等待状态
- TIMED_WAITING 等待指定的时间从新被唤醒的状态
- TERMINATED 执行完成
7.sleep() 和 wait() 有什么区别?
- 类的不一样:sleep() 来自 Thread,wait() 来自 Object。
- 释放锁:sleep() 不释放锁;wait() 释放锁。
- 用法不一样:sleep() 时间到会自动恢复;wait() 可使用 notify()/notifyAll()直接唤醒。
8.notify()和 notifyAll()有什么区别?
- notifyAll()会唤醒全部的线程,notify()以后唤醒一个线程。notifyAll() 调用后,会将所有线程由等待池移到锁池,而后参与锁的竞争,竞争成功则继续执行,若是不成功则留在锁池等待锁被释放后再次参与竞争。而 notify()只会唤醒一个线程,具体唤醒哪个线程由虚拟机控制。
9.线程的 run() 和 start() 有什么区别?
- start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 能够重复调用,而 start() 只能调用一次。
10.建立线程池有哪几种方式?
- newSingleThreadExecutor():它的特色在于工做线程数目被限制为 1,操做一个无界的工做队列,因此它保证了全部任务的都是被顺序执行,最多会有一个任务处于活动状态,而且不容许使用者改动线程池实例,所以能够避免其改变线程数目;
- newCachedThreadPool():它是一种用来处理大量短期工做任务的线程池,具备几个鲜明特色:它会试图缓存线程并重用,当无缓存线程可用时,就会建立新的工做线程;若是线程闲置的时间超过 60 秒,则被终止并移出缓存;长时间闲置时,这种线程池,不会消耗什么资源。其内部使用 SynchronousQueue 做为工做队列;
- newFixedThreadPool(int nThreads):重用指定数目(nThreads)的线程,其背后使用的是无界的工做队列,任什么时候候最多有 nThreads 个工做线程是活动的。这意味着,若是任务数量超过了活动队列数目,将在工做队列中等待空闲线程出现;若是有工做线程退出,将会有新的工做线程被建立,以补足指定的数目 nThreads;
- newSingleThreadScheduledExecutor():建立单线程池,返回 ScheduledExecutorService,能够进行定时或周期性的工做调度;
- newScheduledThreadPool(int corePoolSize):和newSingleThreadScheduledExecutor()相似,建立的是个 ScheduledExecutorService,能够进行定时或周期性的工做调度,区别在于单一工做线程仍是多个工做线程;
- newWorkStealingPool(int parallelism):这是一个常常被人忽略的线程池,Java 8 才加入这个建立方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序;
- ThreadPoolExecutor():是最原始的线程池建立,上面1-3建立方式都是对ThreadPoolExecutor的封装。
11.线程池都有哪些状态?
- RUNNING:这是最正常的状态,接受新的任务,处理等待队列中的任务。
- SHUTDOWN:不接受新的任务提交,可是会继续处理等待队列中的任务。
- STOP:不接受新的任务提交,再也不处理等待队列中的任务,中断正在执行任务的线程。
- TIDYING:全部的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()。
- TERMINATED:terminated()方法结束后,线程池的状态就会变成这个。
12.线程池中 submit() 和 execute() 方法有什么区别?
- execute():只能执行 Runnable 类型的任务。
- submit():能够执行 Runnable 和 Callable 类型的任务。
- Callable 类型的任务能够获取执行的返回值,而 Runnable 执行无返回值。
13. 在 Java 程序中怎么保证多线程的运行安全?
- 方法一:使用安全类,好比 Java. util. concurrent 下的类。
- 方法二:使用自动锁 synchronized。
- 方法三:使用手动锁 Lock。
14.多线程中 synchronized 锁升级的原理是什么?
- synchronized 锁升级原理:在锁对象的对象头里面有一个 threadid 字段,在第一次访问的时候 threadid 为空,jvm 让其持有偏向锁,并将 threadid 设置为其线程 id,再次进入的时候会先判断 threadid 是否与其线程 id 一致,若是一致则能够直接使用此对象,若是不一致,则升级偏向锁为轻量级锁,经过自旋循环必定次数来获取锁,执行必定次数以后,若是尚未正常获取到要使用的对象,此时就会把锁从轻量级升级为重量级锁,此过程就构成了 synchronized 锁的升级。
- 锁的升级的目的:锁升级是为了减低了锁带来的性能消耗。在 Java 6 以后优化 synchronized 的实现方式,使用了偏向锁升级为轻量级锁再升级到重量级锁的方式,从而减低了锁带来的性能消耗。
15.什么是死锁?
- 当线程 A 持有独占锁a,并尝试去获取独占锁 b 的同时,线程 B 持有独占锁 b,并尝试获取独占锁 a 的状况下,就会发生 AB 两个线程因为互相持有对方须要的锁,而发生的阻塞现象,咱们称为死锁。
16.怎么防止死锁?
- 尽可能使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时能够退出防止死锁。
- 尽可能使用 Java. util. concurrent 并发类代替本身手写锁。
- 尽可能下降锁的使用粒度,尽可能不要几个功能用同一把锁。
- 尽可能减小同步的代码块。
17.ThreadLocal 是什么?有哪些使用场景?
- ThreadLocal 为每一个使用该变量的线程提供独立的变量副本,因此每个线程均可以独立地改变本身的副本,而不会影响其它线程所对应的副本。
- ThreadLocal 的经典使用场景是数据库链接和 session 管理等。
18.说一下 synchronized 底层实现原理?
- synchronized 是由一对 monitorenter/monitorexit 指令实现的,monitor 对象是同步的基本实现单元。在 Java 6 以前,monitor 的实现彻底是依靠操做系统内部的互斥锁,由于须要进行用户态到内核态的切换,因此同步操做是一个无差异的重量级操做,性能也很低。但在 Java 6 的时候,Java 虚拟机 对此进行了大刀阔斧地改进,提供了三种不一样的 monitor 实现,也就是常说的三种不一样的锁:偏向锁(Biased Locking)、轻量级锁和重量级锁,大大改进了其性能。
19. synchronized 和 volatile 的区别是什么?
- volatile 是变量修饰符;synchronized 是修饰类、方法、代码段。
- volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则能够保证变量的修改可见性和原子性。
- volatile 不会形成线程的阻塞;synchronized 可能会形成线程的阻塞。
20. synchronized 和 Lock 有什么区别?
- synchronized 能够给类、方法、代码块加锁;而 lock 只能给代码块加锁。
- synchronized 不须要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会形成死锁;而 lock 须要本身加锁和释放锁,若是使用不当没有 unLock()去释放锁就会形成死锁。
- 经过 Lock 能够知道有没有成功获取锁,而 synchronized 却没法办到。
21. synchronized 和 ReentrantLock 区别是什么?
- synchronized 早期的实现比较低效,对比 ReentrantLock,大多数场景性能都相差较大,可是在 Java 6 中对 synchronized 进行了很是多的改进。
- 主要区别以下:
- ReentrantLock 使用起来比较灵活,可是必须有释放锁的配合动做;
- ReentrantLock 必须手动获取与释放锁,而 synchronized 不须要手动释放和开启锁;
- ReentrantLock 只适用于代码块锁,而 synchronized 可用于修饰方法、代码块等。
- volatile 标记的变量不会被编译器优化;synchronized 标记的变量能够被编译器优化。
22. 说一下 atomic 的原理?
- atomic 主要利用 CAS (Compare And Wwap) 和 volatile 和 native 方法来保证原子操做,从而避免 synchronized 的高开销,执行效率大为提高。
反射
1. 什么是反射?
- 反射是在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。
2. 什么是 Java 序列化?什么状况下须要序列化?
- Java 序列化是为了保存各类对象在内存中的状态,而且能够把保存的对象状态再读出来。
- 如下状况须要使用 Java 序列化:
- 想把的内存中的对象状态保存到一个文件中或者数据库中时候;
- 想用套接字在网络上传送对象的时候;
- 想经过RMI(远程方法调用)传输对象的时候。
3. 动态代理是什么?有哪些应用?
- 动态代理是运行时动态生成代理类。
- 动态代理的应用有 spring aop、hibernate 数据查询、测试框架的后端 mock、rpc,Java注解对象获取等。
4. 怎么实现动态代理?
- JDK 原生动态代理和 cglib 动态代理。JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。
对象拷贝
1. 为何要使用克隆?
- 克隆的对象可能包含一些已经修改过的属性,而 new 出来的对象的属性都仍是初始化时候的值,因此当须要一个新的对象来保存当前对象的“状态”就靠克隆方法了。
2. 如何实现对象克隆?
- 实现 Cloneable 接口并重写 Object 类中的 clone() 方法。
- 实现 Serializable 接口,经过对象的序列化和反序列化实现克隆,能够实现真正的深度克隆。
3. 深拷贝和浅拷贝区别是什么?
- 浅克隆:当对象被复制时只复制它自己和其中包含的值类型的成员变量,而引用类型的成员对象并无复制。
- 深克隆:除了对象自己被复制外,对象所包含的全部成员变量也将复制。
Java Web
1. JSP 和 servlet 有什么区别?
- JSP 是 servlet 技术的扩展,本质上就是 servlet 的简易方式。servlet 和 JSP 最主要的不一样点在于,servlet 的应用逻辑是在 Java 文件中,而且彻底从表示层中的 html 里分离开来,而 JSP 的状况是 Java 和 html 能够组合成一个扩展名为 JSP 的文件。JSP 侧重于视图,servlet 主要用于控制逻辑。
2. JSP 有哪些内置对象?做用分别是什么?
- JSP 有 9 大内置对象:
- request:封装客户端的请求,其中包含来自 get 或 post 请求的参数;
- response:封装服务器对客户端的响应;
- pageContext:经过该对象能够获取其余对象;
- session:封装用户会话的对象;
- application:封装服务器运行环境的对象;
- out:输出服务器响应的输出流对象;
- config:Web 应用的配置对象;
- page:JSP 页面自己(至关于 Java 程序中的 this);
- exception:封装页面抛出异常的对象。
3. 说一下 JSP 的 4 种做用域?
- page:表明与一个页面相关的对象和属性。
- request:表明与客户端发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;须要在页面显示的临时数据能够置于此做用域。
- session:表明与某个用户与服务器创建的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户本身的 session 中。
- application:表明与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局做用域。
4. session 和 cookie 有什么区别?
- 存储位置不一样:session 存储在服务器端;cookie 存储在浏览器端。
- 安全性不一样:cookie 安全性通常,在浏览器存储,能够被伪造和修改。
- 容量和个数限制:cookie 有容量限制,每一个站点下的 cookie 也有个数限制。
- 存储的多样性:session 能够存储在 Redis 中、数据库中、应用程序中;而 cookie 只能存储在浏览器中。
5. 说一下 session 的工做原理?
- session 的工做原理是客户端登陆完成以后,服务器会建立对应的 session,session 建立完以后,会把 session 的 id 发送给客户端,客户端再存储到浏览器中。这样客户端每次访问服务器时,都会带着 sessionid,服务器拿到 sessionid 以后,在内存找到与之对应的 session 这样就能够正常工做了。
6. 若是客户端禁止 cookie 能实现 session 还能用吗?
- 能够用,session 只是依赖 cookie 存储 sessionid,若是 cookie 被禁用了,可使用 url 中添加 sessionid 的方式保证 session 能正常使用。
7. spring mvc 和 struts 的区别是什么?
- 拦截级别:struts2 是类级别的拦截;spring mvc 是方法级别的拦截。
- 数据独立性:spring mvc 的方法之间基本上独立的,独享 request 和 response 数据,请求数据经过参数获取,处理结果经过 ModelMap 交回给框架,方法之间不共享变量;而 struts2 虽然方法之间也是独立的,但其全部 action 变量是共享的,这不会影响程序运行,却给咱们编码和读程序时带来了必定的麻烦。
- 拦截机制:struts2 有以本身的 interceptor 机制,spring mvc 用的是独立的 aop 方式,这样致使struts2 的配置文件量比 spring mvc 大。
- 对 ajax 的支持:spring mvc 集成了ajax,全部 ajax 使用很方便,只须要一个注解 @ResponseBody 就能够实现了;而 struts2 通常须要安装插件或者本身写代码才行。
8. 如何避免 SQL 注入?
- 使用预处理 PreparedStatement。
- 使用正则表达式过滤掉字符中的特殊字符。
9. 什么是 XSS 攻击,如何避免?
- XSS 攻击:即跨站脚本攻击,它是 Web 程序中常见的漏洞。原理是攻击者往 Web 页面里插入恶意的脚本代码(css 代码、Javascript 代码等),当用户浏览该页面时,嵌入其中的脚本代码会被执行,从而达到恶意攻击用户的目的,如盗取用户 cookie、破坏页面结构、重定向到其余网站等。
- 预防 XSS 的核心是必须对输入的数据作过滤处理。
10. 什么是 CSRF 攻击,如何避免?
- CSRF:Cross-Site Request Forgery(中文:跨站请求伪造),能够理解为攻击者盗用了你的身份,以你的名义发送恶意请求,好比:以你名义发送邮件、发消息、购买商品,虚拟货币转帐等。
- 防护手段:
- 验证请求来源地址;
- 关键操做添加验证码;
- 在请求地址添加 token 并验证。
异常
1. throw 和 throws 的区别?
- throw:是真实抛出一个异常。
- throws:是声明可能会抛出一个异常。
2. final、finally、finalize 有什么区别?
- final:是修饰符,若是修饰类,此类不能被继承;若是修饰方法和变量,则表示此方法和此变量不能在被改变,只能使用。
- finally:是 try{} catch{} finally{} 最后一部分,表示不论发生任何状况都会执行,finally 部分能够省略,但若是 finally 部分存在,则必定会执行 finally 里面的代码。
- finalize: 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。
3. try-catch-finally 中哪一个部分能够省略?
- try-catch-finally 其中 catch 和 finally 均可以被省略,可是不能同时省略,也就是说有 try 的时候,必须后面跟一个 catch 或者 finally。
4. try-catch-finally 中,若是 catch 中 return 了,finally 还会执行吗?
- finally 必定会执行,即便是 catch 中 return 了,catch 中的 return 会等 finally 中的代码执行完以后,才会执行。
78. 常见的异常类有哪些?
- NullPointerException 空指针异常
- ClassNotFoundException 指定类不存在
- NumberFormatException 字符串转换为数字异常
- IndexOutOfBoundsException 数组下标越界异常
- ClassCastException 数据类型转换异常
- FileNotFoundException 文件未找到异常
- NoSuchMethodException 方法不存在异常
- IOException IO 异常
- SocketException Socket 异常
网络
1. http 响应码 301 和 302 表明的是什么?有什么区别?
- 301:永久重定向。
- 302:暂时重定向。
- 它们的区别是,301 对搜索引擎优化(SEO)更加有利;302 有被提示为网络拦截的风险。
2. forward 和 redirect 的区别?
- forward 是转发 和 redirect 是重定向:
- 地址栏 url 显示:foward url 不会发生改变,redirect url 会发生改变;
- 数据共享:forward 能够共享 request 里的数据,redirect 不能共享;
- 效率:forward 比 redirect 效率高。
3. 简述 tcp 和 udp的区别?
- tcp 和 udp 是 OSI 模型中的运输层中的协议。tcp 提供可靠的通讯传输,而 udp 则常被用于让广播和细节控制交给应用的通讯传输。
- 二者的区别大体以下:
- tcp 面向链接,udp 面向非链接即发送数据前不须要创建连接;
- tcp 提供可靠的服务(数据传输),udp 没法保证;
- tcp 面向字节流,udp 面向报文;
- tcp 数据传输慢,udp 数据传输快;
4. tcp 为何要三次握手,两次不行吗?为何?
- 若是采用两次握手,那么只要服务器发出确认数据包就会创建链接,但因为客户端此时并未响应服务器端的请求,那此时服务器端就会一直在等待客户端,这样服务器端就白白浪费了必定的资源。若采用三次握手,服务器端没有收到来自客户端的再此确认,则就会知道客户端并无要求创建请求,就不会浪费服务器的资源。
5. 说一下 tcp 粘包是怎么产生的?
- tcp 粘包可能发生在发送端或者接收端,分别来看两端各类产生粘包的缘由:
- 发送端粘包:发送端须要等缓冲区满才发送出去,形成粘包;
- 接收方粘包:接收方不及时接收缓冲区的包,形成多个包接收。
6. OSI 的七层模型都有哪些?
- 物理层:利用传输介质为数据链路层提供物理链接,实现比特流的透明传输。
- 数据链路层:负责创建和管理节点间的链路。
- 网络层:经过路由选择算法,为报文或分组经过通讯子网选择最适当的路径。
- 传输层:向用户提供可靠的端到端的差错和流量控制,保证报文的正确传输。
- 会话层:向两个实体的表示层提供创建和使用链接的方法。
- 表示层:处理用户信息的表示问题,如编码、数据格式转换和加密解密等。
- 应用层:直接向用户提供服务,完成用户但愿在网络上完成的各类工做。
7. get 和 post 请求有哪些区别?
- get 请求会被浏览器主动缓存,而 post 不会。
- get 传递参数有大小限制,而 post 没有。
- post 参数传输更安全,get 的参数会明文限制在 url 上,post 不会。
8. 如何实现跨域?
- 实现跨域有如下几种方案:
- 服务器端运行跨域 设置 CORS 等于 *;
- 在单个接口使用注解 @CrossOrigin 运行跨域;
- 使用 jsonp 跨域;
9. 说一下 JSONP 实现原理?
- jsonp:JSON with Padding,它是利用script标签的 src 链接能够访问不一样源的特性,加载远程返回的“JS 函数”来执行的。
设计模式
1. 说一下你熟悉的设计模式?
- 单例模式:保证被建立一次,节省系统开销。
- 工厂模式(简单工厂、抽象工厂):解耦代码。
- 观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的全部的依赖者都会收到通知并自动更新。
- 外观模式:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。
- 模版方法模式:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类能够在不改变算法结构的状况下,从新定义算法的步骤。
- 状态模式:容许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
2. 简单工厂和抽象工厂有什么区别?
- 简单工厂:用来生产同一等级结构中的任意产品,对于增长新的产品,无能为力。
- 工厂方法:用来生产同一等级结构中的固定产品,支持增长任意产品。
- 抽象工厂:用来生产不一样产品族的所有产品,对于增长新的产品,无能为力;支持增长产品族。
Spring/Spring MVC
1. 为何要使用 spring?
- spring 提供 ioc 技术,容器会帮你管理依赖的对象,从而不须要本身建立和管理依赖对象了,更轻松的实现了程序的解耦。
- spring 提供了事务支持,使得事务操做变的更加方便。
- spring 提供了面向切片编程,这样能够更方便的处理某一类的问题。
- 更方便的框架集成,spring 能够很方便的集成其余框架,好比 MyBatis、hibernate 等。
2. 解释一下什么是 aop?
- aop 是面向切面编程,经过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
- 简单来讲就是统一处理某一“切面”(类)的问题的编程思想,好比统一处理日志、异常等。
3. 解释一下什么是 ioc?
- ioc:Inversionof Control(中文:控制反转)是 spring 的核心,对于 spring 框架来讲,就是由 spring 来负责控制对象的生命周期和对象间的关系。
- 简单来讲,控制指的是当前对象对内部成员的控制权;控制反转指的是,这种控制权不禁当前对象管理了,由其余(类,第三方容器)来管理。
3. spring 有哪些主要模块?
- spring core:框架的最基础部分,提供 ioc 和依赖注入特性。
- spring context:构建于 core 封装包基础上的 context 封装包,提供了一种框架式的对象访问方法。
- spring dao:Data Access Object 提供了JDBC的抽象层。
- spring aop:提供了面向切面的编程实现,让你能够自定义拦截器、切点等。
- spring Web:提供了针对 Web 开发的集成特性,例如文件上传,利用 servlet listeners 进行 ioc 容器初始化和针对 Web 的 ApplicationContext。
- spring Web mvc:spring 中的 mvc 封装包提供了 Web 应用的 Model-View-Controller(MVC)的实现。
4. spring 经常使用的注入方式有哪些?
- setter 属性注入
- 构造方法注入
- 注解方式注入
5. spring 中的 bean 是线程安全的吗?
- spring 中的 bean 默认是单例模式,spring 框架并无对单例 bean 进行多线程的封装处理。
- 实际上大部分时候 spring bean 无状态的(好比 dao 类),全部某种程度上来讲 bean 也是安全的,但若是 bean 有状态的话(好比 view model 对象),那就要开发者本身去保证线程安全了,最简单的就是改变 bean 的做用域,把“singleton”变动为“prototype”,这样请求 bean 至关于 new Bean()了,因此就能够保证线程安全了。
- 有状态就是有数据存储功能。
- 无状态就是不会保存数据。
6. spring 支持几种 bean 的做用域?
- spring 支持 5 种做用域,以下:
- singleton:spring ioc 容器中只存在一个 bean 实例,bean 以单例模式存在,是系统默认值;
- prototype:每次从容器调用 bean 时都会建立一个新的示例,既每次 getBean()至关于执行 new Bean()操做;
- Web 环境下的做用域:
- request:每次 http 请求都会建立一个 bean;
- session:同一个 http session 共享一个 bean 实例;
- global-session:用于 portlet 容器,由于每一个 portlet 有单独的 session,globalsession 提供一个全局性的 http session。
- 注意: 使用 prototype 做用域须要慎重的思考,由于频繁建立和销毁 bean 会带来很大的性能开销。
7. spring 自动装配 bean 有哪些方式?
- no:默认值,表示没有自动装配,应使用显式 bean 引用进行装配。
- byName:它根据 bean 的名称注入对象依赖项。
- byType:它根据类型注入对象依赖项。
- 构造函数:经过构造函数来注入依赖项,须要设置大量的参数。
- autodetect:容器首先经过构造函数使用 autowire 装配,若是不能,则经过 byType 自动装配。
8. spring 事务实现方式有哪些?
- 声明式事务:声明式事务也有两种实现方式,基于 xml 配置文件的方式和注解方式(在类上添加 @Transaction 注解)。
- 编码方式:提供编码的形式管理和维护事务。
9. 说一下 spring 的事务隔离?
- spring 有五大隔离级别,默认值为 ISOLATION_DEFAULT(使用数据库的设置),其余四个隔离级别和数据库的隔离级别一致:
- ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;
- ISOLATIONREADUNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其余事务读取(会出现幻读、脏读、不可重复读);
- ISOLATIONREADCOMMITTED:提交读,一个事务提交后才能被其余事务读取到(会形成幻读、不可重复读),SQL server 的默认级别;
- ISOLATIONREPEATABLEREAD:可重复读,保证屡次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会形成幻读),MySQL 的默认级别;
- ISOLATION_SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。
- 脏读 :表示一个事务可以读取另外一个事务中还未提交的数据。好比,某个事务尝试插入记录 A,此时该事务还未提交,而后另外一个事务尝试读取到了记录 A。
- 不可重复读 :是指在一个事务内,屡次读同一数据。
- 幻读 :指同一个事务内屡次查询返回的结果集不同。好比同一个事务 A 第一次查询时候有 n 条记录,可是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的缘由也是另一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,全部数据行的记录就变多或者变少了。
10. 说一下 spring mvc 运行流程?
- spring mvc 先将请求发送给 DispatcherServlet。
- DispatcherServlet 查询一个或多个 HandlerMapping,找处处理请求的 Controller。
- DispatcherServlet 再把请求提交到对应的 Controller。
- Controller 进行业务逻辑处理后,会返回一个ModelAndView。
- Dispathcher 查询一个或多个 ViewResolver 视图解析器,找到 ModelAndView 对象指定的视图对象。
- 视图对象负责渲染返回给客户端。
11. spring mvc 有哪些组件?
- 前置控制器 DispatcherServlet。
- 映射控制器 HandlerMapping。
- 处理器 Controller。
- 模型和视图 ModelAndView。
- 视图解析器 ViewResolver。
12. @RequestMapping 的做用是什么?
13. @Autowired 的做用是什么?
- @Autowired 它能够对类成员变量、方法及构造函数进行标注,完成自动装配的工做,经过@Autowired 的使用来消除 set/get 方法。
Spring Boot/Spring Cloud
1. 什么是 spring boot?
- spring boot 是为 spring 服务的,是用来简化新 spring 应用的初始搭建以及开发过程的。
2. 为何要用 spring boot?
- 配置简单
- 独立运行
- 自动装配
- 无代码生成和 xml 配置
- 提供应用监控
- 易上手
- 提高开发效率
3. spring boot 核心配置文件是什么?
- spring boot 核心的两个配置文件:
- bootstrap (. yml 或者 . properties):boostrap 由父 ApplicationContext 加载的,比 applicaton 优先加载,且 boostrap 里面的属性不能被覆盖;
- application (. yml 或者 . properties):用于 spring boot 项目的自动化配置。
4. spring boot 配置文件有哪几种类型?它们有什么区别?
- 配置文件有 . properties 格式和 . yml 格式,它们主要的区别是书法风格不一样。
5. spring boot 有哪些方式能够实现热部署?
- 使用 devtools 启动热部署,添加 devtools 库,在配置文件中把 spring. devtools. restart. enabled 设置为 true;
- 使用 Intellij Idea 编辑器,勾上自动编译或手动从新编译。
6. jpa 和 hibernate 有什么区别?
- jpa 全称 Java Persistence API,是 Java 持久化接口规范,hibernate 属于 jpa 的具体实现。
110. 什么是 spring cloud?
- spring cloud 是一系列框架的有序集合。它利用 spring boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,均可以用 spring boot 的开发风格作到一键启动和部署。
7. spring cloud 断路器的做用是什么?
- 在分布式架构中,断路器模式的做用也是相似的,当某个服务单元发生故障(相似用电器发生短路)以后,经过断路器的故障监控(相似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。
8. spring cloud 的核心组件有哪些?
- Eureka:服务注册于发现。
- Feign:基于动态代理机制,根据注解和选择的机器,拼接请求 url 地址,发起请求。
- Ribbon:实现负载均衡,从一个服务的多台机器中选择一台。
- Hystrix:提供线程池,不一样的服务走不一样的线程池,实现了不一样服务调用的隔离,避免了服务雪崩的问题。
- Zuul:网关管理,由 Zuul 网关转发请求给对应的服务。
Hibernate
1. 为何要使用 hibernate?
- hibernate 是对 jdbc 的封装,大大简化了数据访问层的繁琐的重复性代码。
- hibernate 是一个优秀的 ORM 实现,不少程度上简化了 DAO 层的编码功能。
- 能够很方便的进行数据库的移植工做。
- 提供了缓存机制,是程序执行更改的高效。
2. 什么是 ORM 框架?
- ORM(Object Relation Mapping)对象关系映射,是把数据库中的关系数据映射成为程序中的对象。
- 使用 ORM 的优势:提升了开发效率下降了开发成本、开发更简单更对象化、可移植更强。
3. hibernate 中如何在控制台查看打印的 SQL 语句?
- 在 Config 里面把 hibernate. show_SQL 设置为 true 就能够。但不建议开启,开启以后会下降程序的运行效率。
4. hibernate 有几种查询方式?
- 三种:hql、原生 SQL、条件查询 Criteria。
5. hibernate 实体类能够被定义为 final 吗?
- 实体类能够定义为 final 类,但这样的话就不能使用 hibernate 代理模式下的延迟关联提供性能了,因此不建议定义实体类为 final。
6. 在 hibernate 中使用 Integer 和 int 作映射有什么区别?
- Integer 类型为对象,它的值容许为 null,而 int 属于基础数据类型,值不能为 null。
7. hibernate 是如何工做的?
- 读取并解析配置文件。
- 读取并解析映射文件,建立 SessionFactory。
- 打开 Session。
- 建立事务。
- 进行持久化操做。
- 提交事务。
- 关闭 Session。
- 关闭 SessionFactory。
8. get()和 load()的区别?
- 数据查询时,没有 OID 指定的对象,get() 返回 null;load() 返回一个代理对象。
- load()支持延迟加载;get() 不支持延迟加载。
9. 说一下 hibernate 的缓存机制?
- hibernate 经常使用的缓存有一级缓存和二级缓存:
- 一级缓存:也叫 Session 缓存,只在 Session 做用范围内有效,不须要用户干涉,由 hibernate 自身维护,能够经过:evict(object)清除 object 的缓存;clear()清除一级缓存中的全部缓存;flush()刷出缓存;
- 二级缓存:应用级别的缓存,在全部 Session 中都有效,支持配置第三方的缓存,如:EhCache。
10. hibernate 对象有哪些状态?
- 临时/瞬时状态:直接 new 出来的对象,该对象还没被持久化(没保存在数据库中),不受 Session 管理。
- 持久化状态:当调用 Session 的 save/saveOrupdate/get/load/list 等方法的时候,对象就是持久化状态。
- 游离状态:Session 关闭以后对象就是游离状态。
11. 在 hibernate 中 getCurrentSession 和 openSession 的区别是什么?
- getCurrentSession 会绑定当前线程,而 openSession 则不会。
- getCurrentSession 事务是 Spring 控制的,而且不须要手动关闭,而 openSession 须要咱们本身手动开启和提交事务。
12. hibernate 实体类必需要有无参构造函数吗?为何?
- hibernate 中每一个实体类必须提供一个无参构造函数,由于 hibernate 框架要使用 reflection api,经过调用 ClassnewInstance() 来建立实体类的实例,若是没有无参的构造函数就会抛出异常。
MyBatis
1. MyBatis 中 #{}和 ${}的区别是什么?
- \#{}是预编译处理,${}是字符替换。 在使用 #{}时,MyBatis 会将 SQL 中的 #{}替换成“?”,配合 PreparedStatement 的 set 方法赋值,这样能够有效的防止 SQL 注入,保证程序的运行安全。
2. MyBatis 有几种分页方式?
- 分页方式:逻辑分页和物理分页。
- 逻辑分页: 使用 MyBatis 自带的 RowBounds 进行分页,它是一次性查询不少数据,而后在数据中再进行检索。
- 物理分页: 本身手写 SQL 分页或使用分页插件 PageHelper,去数据库查询指定条数的分页数据的形式。
3. RowBounds 是一次性查询所有结果吗?为何?
- RowBounds 表面是在“全部”数据中检索数据,其实并不是是一次性查询出全部数据,由于 MyBatis 是对 jdbc 的封装,在 jdbc 驱动中有一个 Fetch Size 的配置,它规定了每次最多从数据库查询多少条数据,假如你要查询更多数据,它会在你执行 next()的时候,去查询更多的数据。就比如你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,因此你要取 4 次才能把钱取完。只是对于 jdbc 来讲,当你调用 next()的时候会自动帮你完成查询工做。这样作的好处能够有效的防止内存溢出。
- Fetch Size 官方相关文档:http://t. cn/EfSE2g3
4. MyBatis 逻辑分页和物理分页的区别是什么?
- 逻辑分页是一次性查询不少数据,而后再在结果中检索分页的数据。这样作弊端是须要消耗大量的内存、有内存溢出的风险、对数据库压力较大。
- 物理分页是从数据库查询指定条数的数据,弥补了一次性所有查出的全部数据的种种缺点,好比须要大量的内存,对数据库查询压力较大等问题。
5. MyBatis 是否支持延迟加载?延迟加载的原理是什么?
- MyBatis 支持延迟加载,设置 lazyLoadingEnabled=true 便可。
- 延迟加载的原理的是调用的时候触发加载,而不是在初始化的时候就加载信息。好比调用 a. getB(). getName(),这个时候发现 a. getB() 的值为 null,此时会单独触发事先保存好的关联 B 对象的 SQL,先查询出来 B,而后再调用 a. setB(b),而这时候再调用 a. getB(). getName() 就有值了,这就是延迟加载的基本原理。
6. 说一下 MyBatis 的一级缓存和二级缓存?
- 一级缓存:基于 PerpetualCache 的 HashMap 本地缓存,它的声明周期是和 SQLSession 一致的,有多个 SQLSession 或者分布式的环境中数据库操做,可能会出现脏数据。当 Session flush 或 close 以后,该 Session 中的全部 Cache 就将清空,默认一级缓存是开启的。
- 二级缓存:也是基于 PerpetualCache 的 HashMap 本地缓存,不一样在于其存储做用域为 Mapper 级别的,若是多个SQLSession之间须要共享缓存,则须要使用到二级缓存,而且二级缓存可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类须要实现 Serializable 序列化接口(可用来保存对象的状态)。
- 开启二级缓存数据查询流程:二级缓存 -> 一级缓存 -> 数据库。
- 缓存更新机制:当某一个做用域(一级缓存 Session/二级缓存 Mapper)进行了C/U/D 操做后,默认该做用域下全部 select 中的缓存将被 clear。
7. MyBatis 和 hibernate 的区别有哪些?
- 灵活性:MyBatis 更加灵活,本身能够写 SQL 语句,使用起来比较方便。
- 可移植性:MyBatis 有不少本身写的 SQL,由于每一个数据库的 SQL 能够不相同,因此可移植性比较差。
- 学习和使用门槛:MyBatis 入门比较简单,使用门槛也更低。
- 二级缓存:hibernate 拥有更好的二级缓存,它的二级缓存能够自行更换为第三方的二级缓存。
8. MyBatis 有哪些执行器(Executor)?
- MyBatis 有三种基本的Executor执行器:
- SimpleExecutor:每执行一次 update 或 select 就开启一个 Statement 对象,用完马上关闭 Statement 对象;
- ReuseExecutor:执行 update 或 select,以 SQL 做为 key 查找 Statement 对象,存在就使用,不存在就建立,用完后不关闭 Statement 对象,而是放置于 Map 内供下一次使用。简言之,就是重复使用 Statement 对象;
- BatchExecutor:执行 update(没有 select,jdbc 批处理不支持 select),将全部 SQL 都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个 Statement 对象,每一个 Statement 对象都是 addBatch()完毕后,等待逐一执行 executeBatch()批处理,与 jdbc 批处理相同。
9. MyBatis 分页插件的实现原理是什么?
- 分页插件的基本原理是使用 MyBatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 SQL,而后重写 SQL,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。
10. MyBatis 如何编写一个自定义插件?
- MyBatis 自定义插件针对 MyBatis 四大对象(Executor、StatementHandler、ParameterHandler、ResultSetHandler)进行拦截:
- Executor:拦截内部执行器,它负责调用 StatementHandler 操做数据库,并把结果集经过 ResultSetHandler 进行自动映射,另外它还处理了二级缓存的操做;
- StatementHandler:拦截 SQL 语法构建的处理,它是 MyBatis 直接和数据库执行 SQL 脚本的对象,另外它也实现了 MyBatis 的一级缓存;
- ParameterHandler:拦截参数的处理;
- ResultSetHandler:拦截结果集的处理。
- setProperties 方法是在 MyBatis 进行配置插件的时候能够配置自定义相关属性,即:接口实现对象的参数配置;
- plugin 方法是插件用于封装目标对象的,经过该方法咱们能够返回目标对象自己,也能够返回一个它的代理,能够决定是否要进行拦截进而决定要返回一个什么样的目标对象,官方提供了示例:return Plugin. wrap(target, this);
- intercept 方法就是要进行拦截的时候要执行的方法。
RabbitMQ
1. RabbitMQ 的使用场景有哪些?
- 抢购活动,削峰填谷,防止系统崩塌。
- 延迟信息处理,好比 10 分钟以后给下单未付款的用户发送邮件提醒。
- 解耦系统,对于新增的功能能够单独写模块扩展,好比用户确认评价以后,新增了给用户返积分的功能,这个时候不用在业务代码里添加新增积分的功能,只须要把新增积分的接口订阅确认评价的消息队列便可,后面再添加任何功能只须要订阅对应的消息队列便可。
2. RabbitMQ 有哪些重要的角色?
- RabbitMQ 中重要的角色有:生产者、消费者和代理:
- 生产者:消息的建立者,负责建立和推送数据到消息服务器;
- 消费者:消息的接收方,用于处理数据和确认消息;
- 代理:就是 RabbitMQ 自己,用于扮演“快递”的角色,自己不生产消息,只是扮演“快递”的角色。
3. RabbitMQ 有哪些重要的组件?
- ConnectionFactory(链接管理器):应用程序与Rabbit之间创建链接的管理器,程序代码中使用。
- Channel(信道):消息推送使用的通道。
- Exchange(交换器):用于接受、分配消息。
- Queue(队列):用于存储生产者的消息。
- RoutingKey(路由键):用于把生成者的数据分配到交换器上。
- BindingKey(绑定键):用于把交换器的消息绑定到队列上。
4. RabbitMQ 中 vhost 的做用是什么?
- vhost:每一个 RabbitMQ 都能建立不少 vhost,咱们称之为虚拟主机,每一个虚拟主机其实都是 mini 版的RabbitMQ,它拥有本身的队列,交换器和绑定,拥有本身的权限机制。
5. RabbitMQ 的消息是怎么发送的?
- 首先客户端必须链接到 RabbitMQ 服务器才能发布和消费消息,客户端和 rabbit server 之间会建立一个 tcp 链接,一旦 tcp 打开并经过了认证(认证就是你发送给 rabbit 服务器的用户名和密码),你的客户端和 RabbitMQ 就建立了一条 amqp 信道(channel),信道是建立在“真实” tcp 上的虚拟链接,amqp 命令都是经过信道发送出去的,每一个信道都会有一个惟一的 id,不管是发布消息,订阅队列都是经过这个信道完成的。
6. RabbitMQ 怎么保证消息的稳定性?
- 提供了事务的功能。
- 经过将 channel 设置为 confirm(确认)模式。
7. RabbitMQ 怎么避免消息丢失?
- 把消息持久化磁盘,保证服务器重启消息不丢失。
- 每一个集群中至少有一个物理磁盘,保证消息落入磁盘。
8. 要保证消息持久化成功的条件有哪些?
- 声明队列必须设置持久化 durable 设置为 true.
- 消息推送投递模式必须设置持久化,deliveryMode 设置为 2(持久)。
- 消息已经到达持久化交换器。
- 消息已经到达持久化队列。
- 以上四个条件都知足才能保证消息持久化成功。
9. RabbitMQ 持久化有什么缺点?
- 持久化的缺地就是下降了服务器的吞吐量,由于使用的是磁盘而非内存存储,从而下降了吞吐量。可尽可能使用 ssd 硬盘来缓解吞吐量的问题。
10. RabbitMQ 有几种广播类型?
- direct(默认方式):最基础最简单的模式,发送方把消息发送给订阅方,若是有多个订阅者,默认采起轮询的方式进行消息发送。
- headers:与 direct 相似,只是性能不好,此类型几乎用不到。
- fanout:分发模式,把消费分发给全部订阅者。
- topic:匹配订阅模式,使用正则匹配到消息队列,能匹配到的都能接收到。
11. RabbitMQ 怎么实现延迟消息队列?
- 延迟队列的实现有两种方式:
- 经过消息过时后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能;
- 使用 RabbitMQ-delayed-message-exchange 插件实现延迟功能。
12. RabbitMQ 集群有什么用?
- 集群主要有如下两个用途:
- 高可用:某个服务器出现问题,整个 RabbitMQ 还能够继续使用;
- 高容量:集群能够承载更多的消息量。
13. RabbitMQ 节点的类型有哪些?
- 磁盘节点:消息会存储到磁盘。
- 内存节点:消息都存储在内存中,重启服务器消息丢失,性能高于磁盘类型。
14. RabbitMQ 集群搭建须要注意哪些问题?
- 各节点之间使用“--link”链接,此属性不能忽略。
- 整个集群中必须包含一个磁盘节点。
15. RabbitMQ 每一个节点是其余节点的完整拷贝吗?为何?
- 不是,缘由有如下两个:
- 存储空间的考虑:若是每一个节点都拥有全部队列的彻底拷贝,这样新增节点不但没有新增存储空间,反而增长了更多的冗余数据;
- 性能的考虑:若是每条消息都须要完整拷贝到每个集群节点,那新增节点并无提高处理消息的能力,最可能是保持和单节点相同的性能甚至是更糟。
16. RabbitMQ 集群中惟一一个磁盘节点崩溃了会发生什么状况?
- 不能建立队列
- 不能建立交换器
- 不能建立绑定
- 不能添加用户
- 不能更改权限
- 不能添加和删除集群节点
- 惟一磁盘节点崩溃了,集群是能够保持运行的,但你不能更改任何东西。
17. RabbitMQ 对集群节点中止顺序有要求吗?
- RabbitMQ 对集群的中止的顺序是有要求的,应该先关闭内存节点,最后再关闭磁盘节点。若是顺序刚好相反的话,可能会形成消息的丢失。
Kafka
1. kafka 能够脱离 zookeeper 单独使用吗?为何?
- kafka 不能脱离 zookeeper 单独使用,由于 kafka 使用 zookeeper 管理和协调 kafka 的节点服务器。
2. kafka 有几种数据保留的策略?
- kafka 有两种数据保存策略:按照过时时间保留和按照存储的消息大小保留。
3. kafka 同时设置了 7 天和 10G 清除数据,到第五天的时候消息达到了 10G,这个时候 kafka 将如何处理?
- 这个时候 kafka 会执行数据清除工做,时间和大小不论那个知足条件,都会清空数据。
4. 什么状况会致使 kafka 运行变慢?
5. 使用 kafka 集群须要注意什么?
- 集群的数量不是越多越好,最好不要超过 7 个,由于节点越多,消息复制须要的时间就越长,整个群组的吞吐量就越低。
- 集群数量最好是单数,由于超过一半故障集群就不能用了,设置为单数容错率更高。
Zookeeper
1. zookeeper 是什么?
- zookeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 google chubby 的开源实现,是 hadoop 和 hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
2. zookeeper 都有哪些功能?
- 集群管理:监控节点存活状态、运行请求等。
- 主节点选举:主节点挂掉了以后能够从备用的节点开始新一轮选主,主节点选举说的就是这个选举的过程,使用 zookeeper 能够协助完成这个过程。
- 分布式锁:zookeeper 提供两种锁:独占锁、共享锁。独占锁即一次只能有一个线程使用资源,共享锁是读锁共享,读写互斥,便可以有多线线程同时读同一个资源,若是要使用写锁也只能有一个线程使用。zookeeper能够对分布式锁进行控制。
- 命名服务:在分布式系统中,经过使用命名服务,客户端应用可以根据指定名字来获取资源或服务的地址,提供者等信息。
3. zookeeper 有几种部署模式?
- zookeeper 有三种部署模式:
- 单机部署:一台集群上运行;
- 集群部署:多台集群运行;
- 伪集群部署:一台集群启动多个 zookeeper 实例运行。
4. zookeeper 怎么保证主从节点的状态同步?
- zookeeper 的核心是原子广播,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫作 zab 协议。 zab 协议有两种模式,分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,zab 就进入了恢复模式,当领导者被选举出来,且大多数 server 完成了和 leader 的状态同步之后,恢复模式就结束了。状态同步保证了 leader 和 server 具备相同的系统状态。
5. 集群中为何要有主节点?
- 在分布式环境中,有些业务逻辑只须要集群中的某一台机器进行执行,其余的机器能够共享这个结果,这样能够大大减小重复计算,提升性能,因此就须要主节点。
6. 集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可使用吗?
- 能够继续使用,单数服务器只要没超过一半的服务器宕机就能够继续使用。
7. 说一下 zookeeper 的通知机制?
- 客户端端会对某个 znode 创建一个 watcher 事件,当该 znode 发生变化时,这些客户端会收到 zookeeper 的通知,而后客户端能够根据 znode 变化来作出业务上的改变。
MySQL
1. 数据库的三范式是什么?
- 第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。
- 第二范式:要求实体的属性彻底依赖于主关键字。所谓彻底依赖是指不能存在仅依赖主关键字一部分的属性。
- 第三范式:任何非主属性不依赖于其它非主属性。
2. 一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 MySQL 数据库,又插入了一条数据,此时 id 是几?
- 表类型若是是 MyISAM ,那 id 就是 8。
- 表类型若是是 InnoDB,那 id 就是 6。
- InnoDB 表只会把自增主键的最大 id 记录在内存中,因此重启以后会致使最大 id 丢失。
3. 如何获取当前数据库版本?
- 使用 select version() 获取当前 MySQL 数据库版本。
4. 说一下 ACID 是什么?
- Atomicity(原子性):一个事务(transaction)中的全部操做,或者所有完成,或者所有不完成,不会结束在中间某个环节。事务在执行过程当中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务历来没有执行过同样。即,事务不可分割、不可约简。
- Consistency(一致性):在事务开始以前和事务结束之后,数据库的完整性没有被破坏。这表示写入的资料必须彻底符合全部的预设约束、触发器、级联回滚等。
- Isolation(隔离性):数据库容许多个并发事务同时对其数据进行读写和修改的能力,隔离性能够防止多个事务并发执行时因为交叉执行而致使数据的不一致。事务隔离分为不一样级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- Durability(持久性):事务处理结束后,对数据的修改就是永久的,即使系统故障也不会丢失。
5. char 和 varchar 的区别是什么?
- char(n) :固定长度类型,好比订阅 char(10),当你输入"abc"三个字符的时候,它们占的空间仍是 10 个字节,其余 7 个是空字节。
- chat 优势:效率高;缺点:占用空间;适用场景:存储密码的 md5 值,固定长度的,使用 char 很是合适。
- varchar(n) :可变长度,存储的值是每一个值占用的字节再加上一个用来记录其长度的字节的长度。
- 因此,从空间上考虑 varcahr 比较合适;从效率上考虑 char 比较合适,两者使用须要权衡。
6. float 和 double 的区别是什么?
- float 最多能够存储 8 位的十进制数,并在内存中占 4 字节。
- double 最可能够存储 16 位的十进制数,并在内存中占 8 字节。
7. MySQL 的内链接、左链接、右链接有什么区别?
- 内链接关键字:inner join;左链接:left join;右链接:right join。
- 内链接是把匹配的关联数据显示出来;左链接是左边的表所有显示出来,右边的表显示出符合条件的数据;右链接正好相反。
8. MySQL 索引是怎么实现的?
- 索引是知足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。
- 具体来讲 MySQL 中的索引,不一样的数据引擎实现有所不一样,但目前主流的数据库引擎的索引都是 B+ 树实现的,B+ 树的搜索效率,能够到达二分法的性能,找到数据区域以后就找到了完整的数据结构了,全部索引的性能也是更好的。
9. 怎么验证 MySQL 的索引是否知足需求?
- 使用 explain 查看 SQL 是如何执行查询语句的,从而分析你的索引是否知足需求。
- explain 语法:explain select * from table where type=1。
10. 说一下数据库的事务隔离?
- MySQL 的事务隔离是在 MySQL. ini 配置文件里添加的,在文件的最后添加:
- transaction-isolation = REPEATABLE-READ
- 可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE。
- READ-UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其余事务读取(会出现幻读、脏读、不可重复读)。
- READ-COMMITTED:提交读,一个事务提交后才能被其余事务读取到(会形成幻读、不可重复读)。
- REPEATABLE-READ:可重复读,默认级别,保证屡次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会形成幻读)。
- 脏读 :表示一个事务可以读取另外一个事务中还未提交的数据。好比,某个事务尝试插入记录 A,此时该事务还未提交,而后另外一个事务尝试读取到了记录 A。
- 不可重复读 :是指在一个事务内,屡次读同一数据。
- 幻读 :指同一个事务内屡次查询返回的结果集不同。好比同一个事务 A 第一次查询时候有 n 条记录,可是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的缘由也是另一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,全部数据行的记录就变多或者变少了。
11. 说一下 MySQL 经常使用的引擎?
- InnoDB 引擎:InnoDB 引擎提供了对数据库 acid 事务的支持,而且还提供了行级锁和外键的约束,它的设计的目标就是处理大数据容量的数据库系统。MySQL 运行的时候,InnoDB 会在内存中创建缓冲池,用于缓冲数据和索引。可是该引擎是不支持全文搜索,同时启动也比较的慢,它是不会保存表的行数的,因此当进行 select count(*) from table 指令的时候,须要进行扫描全表。因为锁的粒度小,写操做是不会锁定全表的,因此在并发度较高的场景下使用会提高效率的。
- MyIASM 引擎:MySQL 的默认引擎,但不提供事务的支持,也不支持行级锁和外键。所以当执行插入和更新语句时,即执行写操做的时候须要锁定这个表,因此会致使效率会下降。不过和 InnoDB 不一样的是,MyIASM 引擎是保存了表的行数,因而当进行 select count(*) from table 语句时,能够直接的读取已经保存的值而不须要进行扫描全表。因此,若是表的读操做远远多于写操做时,而且不须要事务的支持的,能够将 MyIASM 做为数据库引擎的首选。
12. 说一下 MySQL 的行锁和表锁?
- MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。
- 表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的几率最高,并发量最低。
- 行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的几率小,并发度最高。
13. 说一下乐观锁和悲观锁?
- 乐观锁:每次去拿数据的时候都认为别人不会修改,因此不会上锁,可是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
- 悲观锁:每次去拿数据的时候都认为别人会修改,因此每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
- 数据库的乐观锁须要本身实现,在表里面添加一个 version 字段,每次修改为功值加 1,这样每次修改的时候先对比一下,本身拥有的 version 和数据库如今的 version 是否一致,若是不一致就不修改,这样就实现了乐观锁。
14. MySQL 问题排查都有哪些手段?
- 使用 show processlist 命令查看当前全部链接信息。
- 使用 explain 命令查询 SQL 语句执行计划。
- 开启慢查询日志,查看慢查询的 SQL。
15. 如何作 MySQL 的性能优化?
- 为搜索字段建立索引。
- 避免使用 select *,列出须要查询的字段。
- 垂直分割分表。
- 选择正确的存储引擎。
Redis
1. Redis 是什么?都有哪些使用场景?
- Redis 是一个使用 C 语言开发的高速缓存数据库。
- Redis 使用场景:
- 记录帖子点赞数、点击数、评论数;
- 缓存近期热帖;
- 缓存文章详情信息;
- 记录用户会话信息。
2. Redis 有哪些功能?
- 数据缓存功能
- 分布式锁的功能
- 支持数据持久化
- 支持事务
- 支持消息队列
3. Redis 和 memcache 有什么区别?
- 存储方式不一样:memcache 把数据所有存在内存之中,断电后会挂掉,数据不能超过内存大小;Redis 有部份存在硬盘上,这样能保证数据的持久性。
- 数据支持类型:memcache 对数据类型支持相对简单;Redis 有复杂的数据类型。
- 使用底层模型不一样:它们之间底层实现方式,以及与客户端之间通讯的应用协议不同,Redis 本身构建了 vm 机制,由于通常的系统调用系统函数的话,会浪费必定的时间去移动和请求。
- value 值大小不一样:Redis 最大能够达到 1gb;memcache 只有 1mb。
4. Redis 为何是单线程的?
- 由于 cpu 不是 Redis 的瓶颈,Redis 的瓶颈最有多是机器内存或者网络带宽。既然单线程容易实现,并且 cpu 又不会成为瓶颈,那就瓜熟蒂落地采用单线程的方案了。
- 关于 Redis 的性能,官方网站也有,普通笔记本轻松处理每秒几十万的请求。
- 并且单线程并不表明就慢 nginx 和 nodejs 也都是高性能单线程的表明。
5. 什么是缓存穿透?怎么解决?
- 缓存穿透:指查询一个必定不存在的数据,因为缓存是不命中时须要从数据库查询,查不到数据则不写入缓存,这将致使这个不存在的数据每次请求都要到数据库去查询,形成缓存穿透。
- 解决方案:最简单粗暴的方法若是一个查询返回的数据为空(无论是数据不存在,仍是系统故障),咱们就把这个空结果进行缓存,但它的过时时间会很短,最长不超过五分钟。
6. Redis 支持的数据类型有哪些?
- Redis 支持的数据类型:string(字符串)、list(列表)、hash(字典)、set(集合)、zset(有序集合)。
7. Redis 支持的 Java 客户端都有哪些?
- 支持的 Java 客户端有 Redisson、jedis、lettuce 等。
8. jedis 和 Redisson 有哪些区别?
- jedis:提供了比较全面的 Redis 命令的支持。
- Redisson:实现了分布式和可扩展的 Java 数据结构,与 jedis 相比 Redisson 的功能相对简单,不支持排序、事务、管道、分区等 Redis 特性。
9. 怎么保证缓存和数据库数据的一致性?
- 合理设置缓存的过时时间。
- 新增、更改、删除数据库操做时同步更新 Redis,可使用事物机制来保证数据的一致性。
9. Redis 持久化有几种方式?
- Redis 的持久化有两种方式,或者说有两种策略:
- RDB(Redis Database):指定的时间间隔能对你的数据进行快照存储。
- AOF(Append Only File):每个收到的写命令都经过write函数追加到文件中。
10. Redis 怎么实现分布式锁?
- Redis 分布式锁其实就是在系统里面占一个“坑”,其余程序也要占“坑”的时候,占用成功了就能够继续执行,失败了就只能放弃或稍后重试。
- 占坑通常使用 setnx(set if not exists)指令,只容许被一个程序占有,使用完调用 del 释放锁。
11. Redis 分布式锁有什么缺陷?
- Redis 分布式锁不能解决超时的问题,分布式锁有一个超时时间,程序的执行若是超出了锁的超时时间就会出现问题。
12. Redis 如何作内存优化?
- 尽可能使用 Redis 的散列表,把相关的信息放到散列表里面存储,而不是把每一个字段单独存储,这样能够有效的减小内存使用。好比将 Web 系统的用户对象,应该放到散列表里面再总体存储到 Redis,而不是把用户的姓名、年龄、密码、邮箱等字段分别设置 key 进行存储。
13. Redis 淘汰策略有哪些?
- volatile-lru:从已设置过时时间的数据集(server. db[i]. expires)中挑选最近最少使用的数据淘汰。
- volatile-ttl:从已设置过时时间的数据集(server. db[i]. expires)中挑选将要过时的数据淘汰。
- volatile-random:从已设置过时时间的数据集(server. db[i]. expires)中任意选择数据淘汰。
- allkeys-lru:从数据集(server. db[i]. dict)中挑选最近最少使用的数据淘汰。
- allkeys-random:从数据集(server. db[i]. dict)中任意选择数据淘汰。
- no-enviction(驱逐):禁止驱逐数据。
- allkeys-random:从数据集(server. db[i]. dict)中任意选择数据淘汰。
14. Redis 常见的性能问题有哪些?该如何解决?
- 主服务器写内存快照,会阻塞主线程的工做,当快照比较大时对性能影响是很是大的,会间断性暂停服务,因此主服务器最好不要写内存快照。
- Redis 主从复制的性能问题,为了主从复制的速度和链接的稳定性,主从库最好在同一个局域网内。
JVM
1. 说一下 JVM 的主要组成部分?及其做用?
- 类加载器(ClassLoader)
- 运行时数据区(Runtime Data Area)
- 执行引擎(Execution Engine)
- 本地库接口(Native Interface)
- 组件的做用: 首先经过类加载器(ClassLoader)会把 Java 代码转换成字节码,运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交个底层操做系统去执行,所以须要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程当中须要调用其余语言的本地库接口(Native Interface)来实现整个程序的功能。
2. 说一下 JVM 运行时数据区?
- 不一样虚拟机的运行时数据区可能略微有所不一样,但都会听从 Java 虚拟机规范, Java 虚拟机规范规定的区域分为如下 5 个部分:
- 程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工做是经过改变这个计数器的值,来选取下一条须要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都须要依赖这个计数器来完成;
- Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表、操做数栈、动态连接、方法出口等信息;
- 本地方法栈(Native Method Stack):与虚拟机栈的做用是同样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;
- Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被全部线程共享的,几乎全部的对象实例都在这里分配内存;
- 方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。
3. 说一下堆栈的区别?
- 功能方面:堆是用来存放对象的,栈是用来执行程序的。
- 共享性:堆是线程共享的,栈是线程私有的。
- 空间大小:堆大小远远大于栈。
4. 队列和栈是什么?有什么区别?
- 队列和栈都是被用来预存储数据的。
- 队列容许先进先出检索元素,但也有例外的状况,Deque 接口容许从两端检索元素。
- 栈和队列很类似,但它运行对元素进行后进先出进行检索。
5. 什么是双亲委派模型?
- 在介绍双亲委派模型以前先说下类加载器。对于任意一个类,都须要由加载它的类加载器和这个类自己一同确立在 JVM 中的惟一性,每个类加载器,都有一个独立的类名称空间。类加载器就是根据指定全限定名称将 class 文件加载到 JVM 内存,而后再转化为 class 对象。
- 类加载器分类:
- 启动类加载器(Bootstrap ClassLoader),是虚拟机自身的一部分,用来加载Java_HOME/lib/目录中的,或者被 -Xbootclasspath 参数所指定的路径中而且被虚拟机识别的类库;
- 其余类加载器:
- 扩展类加载器(Extension ClassLoader):负责加载\lib\ext目录或Java. ext. dirs系统变量指定的路径中的全部类库;
- 应用程序类加载器(Application ClassLoader)。负责加载用户类路径(classpath)上的指定类库,咱们能够直接使用这个类加载器。通常状况,若是咱们没有自定义类加载器默认就是用这个加载器。
- 双亲委派模型:若是一个类加载器收到了类加载的请求,它首先不会本身去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样全部的加载请求都会被传送到顶层的启动类加载器中,只有当父加载没法完成加载请求(它的搜索范围中没找到所需的类)时,子加载器才会尝试去加载类。
6. 说一下类装载的执行过程?
- 类装载分为如下 5 个步骤:
- 加载:根据查找路径找到相应的 class 文件而后导入;
- 检查:检查加载的 class 文件的正确性;
- 准备:给类中的静态变量分配内存空间;
- 解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;
- 初始化:对静态变量和静态代码块执行初始化工做。
7. 怎么判断对象是否能够被回收?
- 通常有两种方法来判断:
- 引用计数器:为每一个对象建立一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就能够被回收。它有一个缺点不能解决循环引用的问题;
- 可达性分析:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证实此对象是能够被回收的。
8. Java 中都有哪些引用类型?
- 强引用:发生 gc 的时候不会被回收。
- 软引用:有用但不是必须的对象,在发生内存溢出以前会被回收。
- 弱引用:有用但不是必须的对象,在下一次GC时会被回收。
- 虚引用(幽灵引用/幻影引用):没法经过虚引用得到对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。
9. 说一下 JVM 有哪些垃圾回收算法?
- 标记-清除算法:标记无用对象,而后进行清除回收。缺点:效率不高,没法清除垃圾碎片。
- 复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另外一块上,而后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。
- 分代算法:根据对象存活周期的不一样将内存划分为几块,通常是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。
10. 说一下 JVM 有哪些垃圾回收器?
- Serial:最先的单线程串行垃圾回收器。
- Serial Old:Serial 垃圾回收器的老年版本,一样也是单线程的,能够做为 CMS 垃圾回收器的备选预案。
- ParNew:是 Serial 的多线程版本。
- Parallel 和 ParNew 收集器相似是多线程的,但 Parallel 是吞吐量优先的收集器,能够牺牲等待时间换取系统的吞吐量。
- Parallel Old 是 Parallel 老生代版本,Parallel 使用的是复制的内存回收算法,Parallel Old 使用的是标记-整理的内存回收算法。
- CMS:一种以得到最短停顿时间为目标的收集器,很是适用 B/S 系统。
- G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 之后的默认 GC 选项。
11. 详细介绍一下 CMS 垃圾回收器?
- CMS 是英文 Concurrent Mark-Sweep 的简称,是以牺牲吞吐量为代价来得到最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器很是适合。在启动 JVM 的参数加上“-XX:+UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器。
- CMS 使用的是标记-清除的算法实现的,因此在 gc 的时候回产生大量的内存碎片,当剩余内存不能知足程序运行要求时,系统将会出现 Concurrent Mode Failure,临时 CMS 会采用 Serial Old 回收器进行垃圾清除,此时的性能将会被下降。
12. 新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
- 新生代回收器:Serial、ParNew、Parallel Scavenge
- 老年代回收器:Serial Old、Parallel Old、CMS
- 整堆回收器:G1
- 新生代垃圾回收器通常采用的是复制算法,复制算法的优势是效率高,缺点是内存利用率低;老年代回收器通常采用的是标记-整理的算法进行垃圾回收。
13. 简述分代垃圾回收器是怎么工做的?
- 分代回收器有两个分区:老生代和新生代,新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。
- 新生代使用的是复制算法,新生代里有 3 个分区:Eden、To Survivor、From Survivor,它们的默认占比是 8:1:1,它的执行流程以下:
- 把 Eden + From Survivor 存活的对象放入 To Survivor 区;
- 清空 Eden 和 From Survivor 分区;
- From Survivor 和 To Survivor 分区交换,From Survivor 变 To Survivor,To Survivor 变 From Survivor。
- 每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄就 +1,当年龄到达 15(默认配置是 15)时,升级为老生代。大对象也会直接进入老生代。
- 老生代当空间占用到达某个值以后就会触发全局垃圾收回,通常使用标记整理的执行算法。以上这些循环往复就构成了整个分代垃圾回收的总体执行流程。
14. 说一下 JVM 调优的工具?
- JDK 自带了不少监控工具,都位于 JDK 的 bin 目录下,其中最经常使用的是 jconsole 和 jvisualvm 这两款视图监控工具。
- jconsole:用于对 JVM 中的内存、线程和类等进行监控;
- jvisualvm:JDK 自带的全能分析工具,能够分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。
15. 经常使用的 JVM 调优的参数都有哪些?
- -Xms2g:初始化推大小为 2g;
- -Xmx2g:堆最大内存为 2g;
- -XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;
- -XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
- –XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
- -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
- -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
- -XX:+PrintGC:开启打印 gc 信息;
- -XX:+PrintGCDetails:打印 gc 详细信息。