JVM
什么情况下会发生内存溢出?
线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。如果虚拟机在动态扩展栈的时候无法申请到足够的内存空间,则抛出OutOfMemoryError异常
jvm的内存结构
Young(New):virtual to form Eden
Tenured(Old)
Perm
jvm中一次完整的GC流程是怎样的
对象诞生即新生代->eden 在gc过程中如果依旧存活,移动到from,编程Survivor,进行标记代数,检查一定次数后编程老年代
垃圾回收器
serial,parNew,ParallelScavenge,SerialOld,ParallelOld,CMS,G1
出现内存溢出的解决方法
查找出现的地方,进行参数调整和优化
内存模型
内存屏障,保障执行顺序和可见性的一条cpu指令
重排序:为了提高性能,编译器和处理器会对执行进行重拍
happen-befor:操作间执行的顺序关系,有些操作先发生
主内存:共享变量的储存的区域就是主内存
工作内存 每个线程copy本地内存,存储了该线程以读写共享变量的副本
java的反射机制
java程序在允许状态可以动态的获取类的所有方法和属性,并实例化该类,调用的方法功能
Spring
spring加载流程
通过listener入口,核心是在AbstractApplicationContext的refresh方法,在此处装载bean工厂,创建bean实例,拦截器,后置处理器
spring事务的传播性
其中传播属性
_NESTED(嵌套的):如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行,如果当前没有事务,则创建一个事务
_REQUIRED(required必须的,必须要有一个事物):如果当前存在事务,则加入事务,没有事务,创建一个事务
_REQUIRED_NEW(required必须的,必须是新事务):创建一个新的事务,如果当前存在事务则把当前事务挂起,执行新的事务
_SUPPORTS(supports支持,加入事务,或者正常运行):如果当前存在事务,则加入事务,如果当前不存在事务,则以非事务的方法运行
_NOT_SUPPORTED(不支持):以非事务的方式运行,如果当前存在事务,则将事务挂起
_NEVER(不支持任何事务):以非事务的方式运行,如果当前存在事务,抛出异常
_MANDATORY(强制事务):如果当前存在事务,则加入事务,如果没有事务,抛出异常
Spring怎么配置事务
基于XML的事务配置
基于注解的方式配置@Transactional
使用TransactionTemplate
Spring非单例注入的原理,他的生命周期,循环注入的原理,aop实现的原理:
IOC控制反转:
Spring是开源框架,使用框架可以使我们减少工作量,提高工作效率。
并且他是分层结构,在不同的层处理不同的业务,减少代码的耦合度
而spring的核心是IOC控制反转和AOP面向切面编程。
IOC控制反转主要强调的是程序之间的关系是由容器控制的,容器控制对象,控制了对外部资源的容器
而反转即为,在传统的编程中都是由我们创建对象获取依赖对象,而在IOC中是容器帮我们创建对象并注入依赖对象,正是容器帮我们查找和注入对象,对象是被动获取的,所以叫做反转。
AOP面向切面编程:
主要是管理系统层的业务,比如直至,权限事务等。AOP是将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,将其封装成为一个可多次使用的模块(切面)。它将那些与主要业务逻辑无关的的部分提取并封装成切面类减少了重复代码,降低了耦合度,提高了程序的可维护性
核心组件:
bean,context,core单例注入是通过单例BeanFactory创建的,生命周期在创建的时候通过接口实现开启,循环注入是通过后置处理器,aop其实就是用过反射进行动态代理pointcut,advice等
事务的理解:
事物具有一致性,持久性,原子性,隔离性
一致性:事务执行前和执行后是都处于一致的状态
持久性:事务的多数据操作是永久性的
原子性:事务是不可拆分的。事务内的执行语句要么全部成功,要么全部失败
隔离性:一件事务在进行操作时,另一事务不可以对数据进行操作,多个并发事务相互隔离
多线程
多线程的实现方式:
三种:继承Thread类,实现runable接口,线程池启动
volatile的原理,作用
Volatile利用内存栅栏机制保持变量的一致性,不能代替所,只具备数据可见性一致,不具备原子性
线程的生命周期(5+3)新建,就绪,运行,阻塞(其他阻塞,同步阻塞,等待阻塞),死亡
其他阻塞:调用线程的sleep(),join(),IO请求的主动阻塞
等待阻塞:wait()方法进入等待阻塞
同步阻塞:调用资源被其他线程占用(非自旋锁)无法继续时转换为阻塞状态
sleep和wait的区别
sleep的作用
sleep的作用是让线程休眠制定的时间,在时间到达时恢复,也就是说sleep将在接到时间到达事件事恢复线程执行。
wait的作用
调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活活。
sleep来源自thread的静态方法,wait()来源自object的方法
sleep是休眠线程,转为其他阻塞,wait是被动等待,转为等待阻塞
sleep持有锁,wait释放锁
sleep会产生异常,wait不会
sleep需要时间唤醒或者调用interrupt()强行打断。wait需要其他线程调用同一个对象的notify方法才会重新激活
lock和Synchronized的区别
两者都爆出了并发常见下的原子性与可见性,
synchronized的释放锁机制是由其自身控制,结束代码块后自动释放,
lock不会自动释放锁需要在fanily中添加释放锁。添加了类似锁投票,定时锁,和可中断锁等候的一些特性,此外它还提供了在激烈争用请跨系更好的性能
Synchronized原理是什么?
监视器的enter和exit实现
用过哪些原子类,原理是什么
Atomiclnteger;AtomicLong:AtomicReference;AtomicBoolean;基于CAS元原语实现,比较并交换,加载链接/条件储存,最坏的情况下是自旋锁