捡漏暑期面试
- dubbo序列化方式(fastjson2只是格式) 相比JAVA自带的序列化方法的优点
- JAVA自带的序列化方法 咋做的
Java 自带的序列化方法原理
Java的序列化是通过实现Serializable接口,使用ObjectInputStream和ObjectOutputStream来进行对象的序列化和反序列化。这涉及到将对象转换为字节流,以便存储或传输,然后再从字节流恢复对象。Java序列化的一个主要缺点是性能较低,生成的字节流较大,而且在跨语言支持方面有限。
Dubbo 序列化方式的优点
Dubbo 支持多种序列化协议(如 Hessian、Kryo、Protobuf),相比 Java 原生序列化,核心优势如下:
1. 性能优势
2. 支持除JAVA外的多种语言
3. 扩展性与灵活性
- 动态选择协议:Dubbo 允许为不同服务配置不同序列化方式(如核心服务用 Protobuf,边缘服务用 JSON)。
- 兼容性控制:Protobuf 通过字段编号和
optional
关键字支持向前/向后兼容。 - 定制化:可自定义序列化逻辑(如 Kryo 注册类白名单提升性能)。
典型序列化协议对比
Java 原生序列化示例
1. 实现 Serializable 接口
2. 生成一个序列号 serialVersionUID
这个序列号不是必需的,但还是建议你生成。serialVersionUID 的字面含义是序列化的版本号,只有序列化和反序列化的 serialVersionUID 都相同的情况下,才能够成功地反序列化。
3. 重写 writeObject()/readObject() 方法
根据需求决定是否要重写 writeObject()/readObject() 方法,实现自定义序列化
4.调用 java.io.ObjectOutputStream()方法
最后一步,调用 java.io.ObjectOutputStream 的 writeObject()/readObject() 进行序列化与反序列化。
// 序列化 try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.bin"))) { oos.writeObject(new User("Alice", 25)); // User 需实现 Serializable } // 反序列化 try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.bin"))) { User user = (User) ois.readObject(); }
总结
- Java 原生序列化:简单易用但性能差、体积大,适合本地调试或简单场景。
- Dubbo 序列化:通过高性能协议(如 Kryo、Protobuf)解决 Java 原生缺陷,适合分布式系统的高并发、低延迟场景。
- 实现切面除了AOP还有啥方法
二、非AOP框架的其他方法
- 装饰器模式:通过组合方式包装目标对象,手动添加增强逻辑。例如,为业务类创建装饰类,在调用前后添加日志或事务。适用场景:简单增强,但需为每个目标类编写装饰类。
- 责任链模式:将多个处理逻辑串联成链,每个节点决定是否执行后续操作。例如,Web框架中的过滤器链。优点:灵活扩展,支持动态添加处理逻辑。缺点:需显式调用链式处理,侵入性较强。
- 中间件或框架拦截机制某些框架内置拦截功能,
- 如:Servlet Filter:拦截HTTP请求,实现全局日志或鉴权。
- Spring Interceptor:在Controller方法前后添加逻辑
- 库存预扣减幂等性判断key是什么,说成用户ID_UUID 面试官在引导应该做成商品粒度的,否则会出现同时下单两个商品,一个成功一个重试,面试结束核对确实key是商品ID_UUID
- Clickhouse相比Mysql 好在哪里?我结合实习讲了查询上,提问Clickhouse存储优势 说他列式存储原理是很重要的
- 限流 熔断咋做的
- 实习有难度的点---redis实现业务幂等
- redisson分布式锁
- JVM内存区域
- JVM 堆和栈在内存分配上的区别。
缓存雪崩/击穿 是什么 如何解决
JAVA引用类型和基础数据类型 值传递
垃圾回收:自动释放不再被程序引用的对象的所占用的内存
CMS和G1区别:CMS是分代回收,G1是分区划分Region回收, CMS只回收老年代 G1回收老年代和新生代;CMS是使用“标记-清除”算法,容易产生内存碎片,G1是“标记-整理”算法,进行了空间整合,没有碎片。
> G1收集器的内存结构完全区别去CMS,弱化了CMS原有的分代模型(分代可以是不连续的空间),将堆内存划分成一个个Region(1MB~32MB, 默认2048个分区),这么做的目的是在进行收集时不必在全堆范围内进行。它主要特点在于达到可控的停顿时间,用户可以指定收集操作在多长时间内完成,即G1提供了接近实时的收集特性。G1步骤:
可达性分析法是如何解决引用计数法存在的A引用B B又引用A 循环引用的问题?(因为自己没懂GCRoots 可达性分析法, 面试管就:如果让你设计会如何设计(我思考扯了 有向无环图+连通分量)
可达性分析:GCRoots通常包括比如活动线程的栈帧中的局部变量、静态变量、JNI引用等。这些都是程序运行中肯定在使用的对象,作为可达性分析的起点。 GCRoots一定是正在被引用的,A引用B B又引用A
- 由于A和B不在任何GCRoots的引用链上,遍历时不会被标记为存活。无论它们内部如何循环引用,最终都会被判定为不可达对象,从而被回收。
被质疑为啥在DobboFilter里拦截的东西放到ThreadLocal中,(方便同一线程的其他服务获取/RPC.Context也可以隐式传递)
ThreadLocal为啥不设置成强引用 强引用更不会被回收
为啥不去guoyangqi:钱少+情商低感觉无法晋升+还是追求技术从中获取成就感 我想赚钱支撑小资低奢生活 出国游(这又有啥不好启齿的)
智力题 大文件小内存排序 分治归并(最小堆 多路归并 bitmap)
静态代理
静态代理,又叫编译时代理,就是在编译的时候,已经存在代理类,运行时直接调用的方式。说的通俗一点,就是自己手动写代码实现代理类的方式。
AOP缺点,为啥不都用AOP 还要使用new()创建对象:
a. 性能:因反射或字节码生成,有一定性能损耗。而使用new()创建对象 直接内存分配和方法调用,性能更高。依赖条件:AOP需目标类实现接口(JDK Proxy)或非final类(CGLIB)。 new()创建对象 无特殊要求,直接调用构造函数即可。
b. private方法无法被AOP拦截
* 一条update会发生什么
* undo log 和redo log区别
* Mysql索引 主键索引 聚集索引和二级索引
* 分片,原来是节点数是32,现在要变成64,怎么办?我说了一致性哈希,追问现有的32个节点上的数据怎么办,我说 重新路由
* Redis高可用