前言:
作为万千项目组中的一员,特能理解面试造火箭之术对平时专注需求实现的开发者不友好,客观的说,换位思考,我完全能理解,但是面试官林林总总,不能期望能遇到一个耐心且技术真正优秀的人来发掘你,作为一个可能的面试者,所要做的正是适应环境,顺势而为乃识时务,另外,我相信每个专注实现的工程师,智商也完全在线,可能架构师之路你已经完成了90%,只需要再花点时间收拾自己,就能完成至少是表面上的质的蜕变。
以下是一份快速的目录,如果需要深入进入模块,请自行搜索查阅。
一、JVM
https://blog.csdn.net/qq_41701956/article/details/81664921
1、java内存模型 必会(以jdk7为例)
方法区、-内存共享区,关键字,存放类静态熟悉,类加载时就会操作。
堆,线程共享,所有的类实例化对象都在这产生和消亡。
虚拟机栈,线程私有,java动作类指令存放的区域(其实就是各种方法)
本地方法栈,区别于虚拟机栈,这个区域是native方法,虚拟机和宿主机操作的指令存储空间
程序计数器,线程控制切换存储的区域。
2、垃圾回收机制
2.1引用计数法(状态区分+标记)
2.2 可达性分析(略)
2.3 具体回收
堆中的回收:
强引用,例如new出来的,内存爆了也不回收。
软引用,次于强引用,内存溢出之前才收拾。
弱引用,每次gc,gc重点照顾对象,都会被干掉。
虚引用,其实就是个标记,只是为了gc时给通知。
方法区中的回收:
方法区也不是完全不能回收的,只是被回收的概率很低,主要目标为
废弃的常量(压根没引用,这种常量ide也会提示)
无用的类(实例全挂,加载器已死,反射路径也不存在)
3、类加载机制
=========虚拟机主导开始===========
加载(二进制class进内存)---针对class本身
验证,文件头信息 版本等
准备,重要,分配内存并且给默认值
解析,常量池的符号引用改为直接引用
=========虚拟机主导结束====
初始化-实例化一个对象,或者直接拿静态类来操作了 必然触发的几个场景
new 反射 父类被子类初始化 main方法执行。
使用--也可以不实例对象直接使用,当然一般是实例化对象使用
卸载-对象全部消亡。
双亲委派(parent-delegation),请尽量不要用中文,这四个字误导性极强,简而言之,先啃老拿来主义,只要当顶级加载器都不在时,才考虑自己加载。
String HashMap类不会被修改,因为他们只会被bootstrap加载器加载,对应jdk中rt.jar里的玩意。
扩展类加载器,对应ext.xx.jar的类
应用程序加载器,对应自己的classspath,比如造一个NoClassDefFoundError,编译时ok,运行时把classpath下的class文件删除,就会报这个。
而ClassNotFoundException比这更靠前,如果尝试加载class进内存时找不到就会报。
二、JDK源码
1、集合的数据结构
https://www.jianshu.com/p/55de7ab8efd5
ArrayList(数组)有序紧挨 好读不好写
Vector(数组实现、线程同步)
LinkList(链表)有序有坐标 好写不好读
HashSet(Hash 表)
hash桶 必会
TreeSet(二叉树) 有tree皆可排序
LinkHashSet(HashSet+LinkedHashMap) 有link皆有顺序
HashMap(数组+链表+红黑树(jdk8内容长度超过8个时生效))
三个指标
capacity 容量
loadFactor 负载因子 默认0.75
threshold 扩容阈值=容量*负载因子
HashTable --HashMap+锁 线程安全,已无存在必要。
ConcurrentHashMap HashMap+分段锁,默认16段
TreeMap 可排序
LinkHashMap 记录插入顺序
2、常量池设计
String a="1";
String b="1";
String c=new String("1");
ab地址完全相等,当然c地址就不一样了。
3、hashcode和equals方法
hashcode一样 equals可以不一样,equals一样,理论上hashcode也会一样。
hashcode常用的计算,就是把对象变成char或者int数组,然后进行
31倍数相乘迭代的散列。
为什么用31,31是素数,且32就是2的5次方,移位运算方便。
三、java开发常用框架原理
1、spring相关
ioc或者叫DI
https://www.cnblogs.com/superjt/p/4311577.html
依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。
IOC Service Provider 为被注入对象提供被依赖对象也有如下几种方式:构造方法注入、stter方法注入、接口注入。
反转的意思是,原来你要什么需要自己组装,现在是你要什么,让容器自动装配给你。
解决循环依赖 ,三级缓存解决(一级单例,二级占坑,三级完全)
singletonObjects
earlySingletonObjects
singletonFactories
https://www.cnblogs.com/longy2012/articles/12834762.html
aop
面向切面编程
实现方式有aspectj(静态织入),cglib和jdk动态代理
前置 后置 环绕 返回 异常 5种通知
https://blog.csdn.net/JinXYan/article/details/89302126
mvc相关
请求 dispatch分发 map寻址 adapter转化 调用 处理 返回视图 解析渲染
https://blog.csdn.net/number_oneengineer/article/details/82775419
事务级别
2、springboot相关
jar包全家桶+注解配置+main入口=starter springboot
注解
@SpringBootApplication = (默认属性)@Configuration + @EnableAutoConfiguration + @ComponentScan。
https://www.cnblogs.com/jstarseven/p/11087157.html
提供各种statrer 统一的main方法入口 yml配置注入实例对象。
四、开源中间件
1、zookeeper
https://blog.csdn.net/lingbo229/article/details/81052078
zookeeper=文件系统+通知机制。
5个用处
命名服务 配置管理(zk中心) 集群管理 分布式锁 队列管理
memcaced 和redis
https://www.cnblogs.com/middleware/articles/9052394.html
memcahced集群
https://blog.csdn.net/dailywater/article/details/50876865
dubbo
spi全名叫server provider interface,是一种服务发现机制,可以在运行时,通过全限定路径名,动态的加载接口的实现类。
dubbo在这个基础上做了扩展,比如说jdk的spi,他会不管你需不需要用到这些类,只要你启动就加载进来,而我们一些方法就想用到他的时候再用反射来加载,就像spring的beanfactory一样。
此外,在如果一个类需要扩展的话,dubbo用装饰者模式来实现了对类的扩展,相当于aop的实现。
消息队列:解耦
https://blog.csdn.net/acaoye/article/details/82967172
五、设计模式
代理模式解决多短信网关或者文件服务
建造者模式方便实例对象
工厂模式
适配器模式 重构常用
装饰者模式
模板模式
策略模式 去掉if else
https://blog.csdn.net/qq_39404258/article/details/81175421
https://www.cnblogs.com/blackdd/p/12364112.html
mybatis中用到的9种设计模式
1、Builder模式:例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder
2、工厂模式:例如SqlSessionFactory、ObjectFactory、MapperProxyFactory
3、单例模式:例如LogFactory、ErrorContext
4、代理模式:mybatis实现的核心,比如MapperProxy、ConnectionLogger、用的jdk的动态代理,还有executor.loader包使用了cglib或者javassist达到延迟加载的效果
5、组合模式:例如SqlNode和各个子类ChooseSqlNode等
6、模板方法模式:例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler
7、适配器模式:例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现
8、装饰者模式:例如Cache包中的cache.decorators子包中的各个装饰者的实现
9、迭代器模式:例如迭代器模式PropertyTokenizer
六、网络相关
TCPIP 化osi7层为4层
物理 数据链路 网络 传输 会话 表示 应用
https://blog.csdn.net/weixin_42621338/article/details/87354737
三次握手 四次挥手
四次握手是因为对比与握手的被动接收方,他还需要一次握手传输未传输完的信息来保证信息的完整性。
七、解决方案
nio-
NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector。传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。
https://blog.csdn.net/forezp/article/details/88414741
https://blog.csdn.net/qq_36520235/article/details/81318189?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
多线程
方法
thread runable callbale 线程池创建
start方法开启
常规线程 守护线程
如果只剩守护线程 则jvm退出
线程状态
新建 就绪 阻塞 运行 死亡
https://www.jianshu.com/p/3e88a5fe75f0
线程必要时 加锁
synchronized是悲观锁
加version可以做乐观锁
ELK搭建日志系统
ELK Stack 是Elasticsearch、Logstash、Kiban三个开源软件的组合。在实时数据检索和分析场合,三者通常是配合共用,而且又都先后归于 Elastic.co 公司名下,故有此简称。
https://blog.csdn.net/bbwangj/article/details/80600698
八、数据库
mysql事务级别
默认是可重复读 第二档强
https://www.cnblogs.com/wyaokai/p/10921323.html
sql优化
创建索引,索引字段设置成notnull ,注意不走索引的情况:%打头的like语句,!=用> union <实现,is
null的查询,注意最左匹配原则;再有就是去优化limit,先查id再limit,查询别用select*,防止表修改后报错或者查询冗余
SQL的执行顺序:from---where--group by---having---select---order by
https://www.jianshu.com/p/a61f012e84d5
九、数据结构和算法
冒泡
十、其他
CAP 原理
ZAP协议
volatile --防止指令重排 和final对应
java8特性 接口可默认实现 lambada表达式 集合结构修改 函数式接口
https://www.jianshu.com/p/0bf8fe0f153b