网站首页 > 博客文章 正文
Java高级开发工程师面试题详解答案
一、JVM相关
1. JVM内存结构及版本变化
答案:
JDK8内存结构:
1. 程序计数器:线程私有,记录执行位置
2. Java虚拟机栈:线程私有,存储栈帧
3. 本地方法栈:Native方法调用
4. 堆:所有对象实例和数组
5. 方法区(元空间):类信息、常量、静态变量(JDK8用本地内存实现)
JDK8 vs JDK7主要变化:
- 永久代(PermGen)被元空间(Metaspace)取代
- 字符串常量池移至堆中
- 方法区实现改为使用本地内存
JDK11+新增特性:
- ZGC/Shenandoah垃圾收集器
- 类数据共享(CDS)优化
- Epsilon无操作垃圾收集器
2. Full GC诊断与解决案例
答案:
诊断步骤:
1. 开启GC日志:-XX:+PrintGCDetails -XX:+PrintGCDateStamps
2. 使用jstat -gcutil监控实时GC情况
3. 内存溢出时生成dump文件:-XX:+
HeapDumpOnOutOfMemoryError常见原因及解决方案:
案例:电商系统促销期间频繁Full GC
- 现象:每分钟2-3次Full GC,STW达3秒
- 分析:
a. MAT分析发现HashMap缓存未限制大小
b. 年轻代太小导致过早晋升(-Xmn调整)
c. 存在内存泄漏:未关闭的数据库连接
- 解决方案:
a. 引入Caffeine缓存替换HashMap
b. 调整新生代与老年代比例1:2
c. 添加连接池监控
效果:Full GC降为每天1次,STW<500ms
二、并发编程
3. ConcurrentHashMap优化
答案:
JDK8优化点:
1. 数据结构:数组+链表+红黑树
2. 锁粒度:从分段锁改为CAS+synchronized锁单个桶
3. size计算:基于CounterCell的分段计数
4. 扩容协助:多线程协同扩容
size()实现原理:
final long sumCount() {
CounterCell[] as = counterCells;
long sum = baseCount;
if (as != null) {
for (CounterCell a : as) {
if (a != null)
sum += a.value;
}
}
return sum;
}
通过baseCount+CounterCell数组的方式减少竞争,最终一致性而非绝对准确
4. 高并发秒杀系统设计
答案:
分层设计:
1. 接入层:
- 限流:Guava RateLimiter+分布式限流
- 防刷:IP/用户行为分析
2. 服务层:
- 缓存预热:Redis提前加载库存
- 库存扣减:Lua脚本保证原子性
- 队列削峰:RocketMQ异步下单
3. 数据层:
- 分库分表:按活动ID分片
- 乐观锁:update inventory set count=count-1 where id=? and count>=1
关键代码:
// Redis库存扣减Lua脚本
String script = "if redis.call('get', KEYS[1]) >= ARGV[1] then " +
"return redis.call('decrby', KEYS[1], ARGV[1]) " +
"else return -1 end"
三、分布式系统
5. CAP理论权衡案例
答案:
支付系统(CP选择):
- 需求:资金数据必须强一致
- 实现:
a. 分布式事务(Seata)
b. 同步复制(Raft协议)
c. 牺牲可用性:事务期间拒绝服务
社交系统(AP选择):
- 需求:高可用比强一致更重要
- 实现:
a. 最终一致性(CQRS)
b. 冲突解决(时间戳/向量时钟)
c. 客户端合并策略
折中方案:
- 本地优先:客户端缓存+后台同步
- 可调一致性:Dynamo风格的N/R/W配置
6. 分布式事务最终一致性方案
答案:
可靠消息方案设计:
1. 本地事务表:
- 业务表与消息表同库,事务保证原子性
2. 定时任务:
- 扫描待发送消息
- 幂等投递(消息ID去重)
3. 补偿机制:
- 状态确认回调
- 死信队列处理
伪代码:
// 1. 业务处理与消息存储
@Transactional
public void createOrder(Order order) {
orderDao.insert(order);
messageDao.save(new Message("order_created", order.getId()));
}
// 2. 消息投递(定时任务)
List<Message> messages = messageDao.findPending();
messages.forEach(msg -> {
try {
mqProducer.send(msg);
messageDao.updateStatus(msg.id, "SENT");
} catch(Exception e) {
// 重试机制
}
});
四、框架原理
7. Spring Bean生命周期
答案:
完整生命周期:
1. 实例化:BeanDefinition→构造函数
2. 属性填充:@Autowired注入
3. Aware回调:BeanNameAware等
4. 初始化前:
BeanPostProcessor.postProcessBeforeInitialization5. 初始化:@PostConstruct、InitializingBean
6. 初始化后:
BeanPostProcessor.postProcessAfterInitialization7. 销毁:@PreDestroy、DisposableBean
性能优化扩展点:
1.
SmartInitializingSingleton:所有单例初始化完成后回调2. ImportSelector:动态加载配置类
3. BeanFactoryPostProcessor:修改BeanDefinition
4. Scope("prototype"):避免无状态Bean的单例竞争
8. MyBatis插件实现分页
答案:
实现原理:
1. 拦截目标:StatementHandler.prepare
2. 改写SQL:根据方言添加LIMIT/OFFSET
3. 线程局部变量:PageHelper.startPage()
核心代码:
@Intercepts(@Signature(type=StatementHandler.class,
method="prepare",
args={Connection.class,Integer.class}))
public class PageInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) {
StatementHandler sh = (StatementHandler)invocation.getTarget();
BoundSql boundSql = sh.getBoundSql();
// 获取分页参数
Page page = PageHelper.getPage();
if(page != null) {
String newSql = boundSql.getSql() +
" LIMIT " + page.getStartRow() + "," + page.getPageSize();
resetSql(sh, boundSql, newSql);
}
return invocation.proceed();
}
private void resetSql(...){...}
}
五、系统设计
9. 分布式配置中心设计
答案:
架构设计:
1. 存储层:
- 多版本配置的KV存储(MySQL+本地缓存)
- 配置变更日志(用于回滚)
2. 服务层:
- 长轮询+增量推送
- 配置加密(APOLLO的Namespace设计)
3. 客户端:
- 多级缓存(内存→本地文件→远程)
- 熔断降级(本地缓存兜底)
高可用保障:
1. 数据同步:基于Raft协议的多副本
2. 灰度发布:按IP/应用分批推送
3. 性能优化:
- 配置分片(zookeeper节点设计)
- 批量拉取(HTTP/2多路复用)
10. 千万级用户分库分表方案
答案:
分片策略:
1. 基因法:user_id后N位作为分片键
- 优点:避免跨分片查询
- 实现:订单表包含user_id后缀
跨分片查询方案:
1. 全局索引表:
- 维护非分片键到分片位置的映射
- 如:通过手机号查user_id再路由
2. 广播表:
- 基础数据全分片冗余存储
3. 分布式查询:
- 合并各分片结果(MyCAT中间件)
典型配置:
# 分16库64表
sharding-column: user_id
algorithm-expression: ds_${user_id % 16}.t_order_${user_id % 64}
以上答案可根据实际项目经验补充具体案例数据。建议准备时:
1. 对每个知识点准备1-2个实战案例
2. 重要的源码片段能手写关键部分
3. 系统设计题多使用架构图辅助说明
猜你喜欢
- 2025-06-24 面试必备!Java核心技术面试100题(java核心面试精讲)
- 2025-06-24 2024最新版java面试题(八股文+场景题)合集!
- 2025-06-24 「开发者成长」5 个刁钻的Java String 面试题
- 2025-06-24 25 年 Java 开发者面试必问 TOP10 核心问题及破题攻略
- 2025-06-24 Java高薪跳槽面试官最爱问的50道题深度解读
- 2025-06-24 Java高频八股文面试题及参考答案(js 八股文)
- 2025-06-24 10 个经典的 Java 集合面试题,看你能否答得上来?
- 2025-06-24 Java面试场景题及答案最全总结(2025版持续更新)
- 2025-06-24 2025年阿里Java面试题库(纯干货,超详细,从题目到答案)
- 2025-06-24 Java面试题及答案最全总结(2025版持续更新)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)