1、对象由什么组成?
对象头、实例数据、对齐填充(占位符)
2、对象头里有什么?
运行时数据、类型指针、数组长度
3、非双亲委派模型有哪两种?
线程上下文类加载器
OSGi
4、JVM的哪些内存需要被回收?
堆内存
5、JVM线程并行和并发的区别?
并行:多条垃圾收集线程同时工作,但此时用户线程处于等待状态;
并发:用户线程与垃圾收集线程同时执行。
6、JVM的指令集有哪两种?
基于栈的指令集(JVM默认)。可移植,但执行速度较慢;
基于寄存器的指令集。主流物理机所用。
7、分布式CAP代表什么?
一致性(Consistency)
可用性(Availability)
分区容忍性(Partitiontolerance)
8、分布式锁的实现方式有哪三种?
数据库锁
缓存锁
ZooKeeper分布式锁
9、分布式回话有几种实现方式?
基于数据库
基于缓存框架(如redis,memcached)
基于NFS
基于cookie
基于tomcat本身的session复制机制
10、观察者模式和发布订阅有什么区别?
后者完全解耦,且有中间代理。
11、过滤器和拦截器的区别?
1)过滤器依赖Servlet;拦截器依赖Web框架如SpringMVC,能起到AOP的效果,通过拦截器可以实现动态代理。
2)过滤器基于函数回调;而拦截器基于Java的反射机制。
3)过滤器可以过滤各种请求,而拦截器只能拦截Controller请求,对诸如直接访问静态资源的请求无能为力。
4)过滤器比拦截器先执行。
5)在一次请求的生命周期中,拦截器可以多次被调用,并且使用很灵活;而过滤器只能在容器初始化时被调用一次。
12、JVM的组成部分有哪些?
类加载器(ClassLoader)
运行时数据区(RuntimeData Area)
执行引擎(ExecutionEngine)
本地库接口(NativeInterface)
13、JVM的运行时数据区分为哪五大部分?
堆、栈、本地方法栈、方法区、程序计数器
14、新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
新生代回收器:Serial、ParNew、ParallelScavenge
老年代回收器:SerialOld、Parallel Old、CMS
整堆回收器:G1
新生代垃圾回收器一般采用的是复制算法,复制算法的优点是效率高,缺点是内存利用率低;老年代回收器一般采用的是标记-整理的算法进行垃圾回收。
15、Minor GC与Full GC分别在什么时候发生?
新生代内存不够用时候发生MinorGC,
Minor GC失败或者JVM内存不够的时候发生FullGC。
16、volatile i++线程安全吗?
不安全。
原因:Java中只有对基本类型变量的赋值和读取是原子操作,如i= 1的赋值操作,但是像j =i或者i++这样的操作都不是原子操作,因为他们都进行了多次原子操作,比如先读取i的值,再将i的值赋值给j,两个原子操作加起来就不是原子操作了。
17、CMS为什么采用标记——清除算法?
CMS主要关注低延迟,因而采用并发方式,清理垃圾时,应用程序还在运行,如果采用压缩算法,则涉及到要移动应用程序的存活对象,此时不停顿,是很难处理的。
一般移动存活对象是需要停顿的,再让应用程序继续运行,但这样停顿时间变长,延迟变大,不符合CMS低延迟的运作模式,所以CMS采用清除算法。
18、成员变量和静态变量分别存在哪里?
成员变量存在堆中,静态变量存在方法区中。
19、反射有哪三种做法?
假设Foo foo=new Foo();
1)通过Object的getClass方法:Class cla = foo.getClass()
2)通过对象实例获取:Class cla = foo.class
3)通过Class.forName方式:Class cla =Class.forName( “xx.xx.Foo” );
20、ArrayList是线程不安全的,轻量级的。如何使ArrayList线程安全?
1)继承Arraylist,然后重写或按需求编写自己的方法,这些方法要写成synchronized,在这些synchronized的方法中调用ArrayList的方法。
2)Listlist = Collections.synchronizedList(new ArrayList());
21、throw 和 throws 的区别?
throw:真实抛出一个异常。
throws:声明可能会抛出一个异常。
22、spring 常用的注入方式有哪些?
setter 属性注入
构造方法注入
注解方式注入
23、JVM有哪些垃圾回收器?
Serial
Serial Old
ParNew
Parallel
Parallel Old
CMS
G1
24、堆用来放什么?
对象实例
数组
25、类加载分为几个步骤?
加载、验证、准备、解析、初始化。最后是使用和卸载
26、如何判断一个对象是否存活?
引用计数法(循环引用问题)
引用链法
27、给对象分配堆内存的方式有哪些?
如果堆内存规整,采用"指针碰撞";
如果堆内存不规整,采用"空闲列表"
28、访问对象有哪些方式?
句柄
直接指针
29、并发创建对象时,有什么处理策略?
1)同步处理
2)本地线程分配缓冲区
30、出现线程安全问题的原因有哪些?
线程切换带来的原子性问题
缓存导致的可见性问题
编译优化带来的有序性问题
31、线程池有哪四种?
newCachedThreadPool:大小无界,适用于执行很多的短期异步任务的小程序,或者负载较轻的服务器
newFixedThreadPool:固定线程数,满足资源管理的需要,适用于负载较重的服务器
newSingleThreadExecutor:单线程,适用于需要保证顺序地执行各个任务
newScheduledThreadPool:创建一个大小无限的线程池,用于定时任务
32、提交任务时,如果线程池队列已满,这时会发生什么?
如果是无界队列,则继续添加任务;
如果是有界队列,会先增加线程数量,线程数量达到某一值后,会采取拒绝策略,默认为AbortPolicy
33、线程池队列的饱和策略有哪些?
AbortPolicy:直接抛异常
CallerRunsPolicy:调用者所在线程来运行任务
DiscardPolicy:不处理,丢弃掉
DiscardOldestPolicy:丢弃队列中最旧的任务
34、CAS有什么问题?
ABA问题
循环时间长开销大;
只能保证一个共享变量的原子操作
35、有哪些线程安全的集合类?
vector、stack、hashtable、enumeration
36、Java线程之间的通信方式有哪两种?
共享内存、消息传递
37、编译器和处理器对指令重排序的类型有哪三种?
1)编译器优化的重排序;
2)指令级并行的重排序;
3)内存系统的重排序
38、处理器如何实现原子操作?
1)使用总线锁保证原子性;
2)使用缓存锁保证原子性
39、Java如何实现原子操作?
1)使用循环CAS;
2)使用锁
40、如何安全地终止线程?
1)中断;
2)使用一个布尔变量以控制是否需要停止任务并终止该线程
41、线程池的任务队列有哪四种?
ArrayBlockingQueue:有界阻塞队列
LinkedBlockingQueue:无界阻塞队列
SynchronousQueue:不存储元素的阻塞队列
PriorityBlockingQueue
42、线程中断的原理是什么?
其它线程通过调用该线程的interrupt()对其进行中断
43、线程调度的方式有哪两种?
协同式线程调度、抢占式线程调度
44、线程的暂停/恢复怎么实现?
等待/通知机制
注:不是问“启停”
43、volatile的实现原理?
编译器生成字节码时,在指令序列中插入内存屏障,防止指令重排
44、volatile有什么特点?
原子性、可见性,但不能保证操作的原子性
45、volatile要实现同步怎么做?
volatile===>CAS===>+循环===>原子===>+有序===>锁(同步)
注:原子有序即同步
46、如何减少线程的上下文切换?
无锁并发编程
CAS算法
使用最少线程和使用协程
47、对象如何延迟初始化?
基于volatile的解决方案、基于类初始化的解决方案
注:不能用双重检查锁定
48、指令重排序的缺点?如何解决?
重排序可能会导致多线程程序出现内存可见性问题。
禁止特定类型的编译器重排序;通过内存屏障指令,禁止特定类型的处理器重排序。如volatile
49、Java堆是否规整由什么决定?
由采用的垃圾收集器是否带有压缩整理功能决定。
50、重载是什么?
方法具备不同的特征签名(不包含方法返回值)
51、为什么要使用克隆?
想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了。
52、HashMap 的实现原理是什么?
HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。
当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。
当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时使用链表,否则使用红黑树。
53、在 Queue 中 poll()和 remove()有什么区别?
相同点:都是返回第一个元素,并在队列中删除返回的对象。
不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。
54、多线程中 synchronized 锁升级的原理是什么?
synchronized 锁升级原理:在锁对象的对象头里面有一个 thread_id 字段,在第一次访问的时候 thread_id为空,jvm 让其持有偏向锁,并将 thread_id 设置为其线程 id,再次进入的时候会先判断 thread_id 是否与其线程 id 一致,如果一致则可以直接使用此对象,如果不一致,则升级偏向锁为轻量级锁,通过自旋循环一定次数来获取锁,执行一定次数之后,如果还没有正常获取到要使用的对象,此时就会把锁从轻量级升级为重量级锁,此过程就构成了 synchronized 锁的升级。
锁的升级的目的:锁升级是为了减低了锁带来的性能消耗。在 Java 6 之后优化 synchronized 的实现方式,使用了偏向锁升级为轻量级锁再升级到重量级锁的方式,从而减低了锁带来的性能消耗。
55、synchronized 底层实现原理是什么?
synchronized 是由一对 monitorenter/monitorexit 指令实现的,monitor 对象是同步的基本实现单元。在 Java 6 之前,monitor 的实现完全是依靠操作系统内部的互斥锁,因为需要进行用户态到内核态的切换,所以同步操作是一个无差别的重量级操作,性能也很低。
但在 Java 6 的时候,Java 虚拟机 对此进行了大刀阔斧地改进,提供了三种不同的 monitor 实现,也就是常说的三种不同的锁:偏向锁(Biased Locking)、轻量级锁和重量级锁,大大改进了其性能。
56、高并发限流有什么算法?
令牌桶算法和漏桶算法
如果要让自己的系统不被打垮,用令牌桶。如果保证别人的系统不被打垮,用漏桶算法
57、高并发时应该采取什么措施保护系统?
缓存、降级、限流。
58、令牌桶算法有几种工作模式?
单速单桶
单速双桶
双速双桶
59、布隆过滤器有什么特点?
如果布隆过滤器判断一个元素存在,那么这个元素可能存在。
如果布隆过滤器判断一个元素不存在,那么这个元素一定不存在。
60、Java默认字符集是哪个?
与操作系统平台有关,在JVM启动时才确定