一、JVM与内存管理
1. 垃圾回收机制对比
2021年面试中,JVM垃圾回收器的选择与调优成为必考题。典型问题如:”CMS与G1回收器的核心差异是什么?在什么场景下选择哪种回收器?”
- CMS(Concurrent Mark Sweep):基于标记-清除算法,强调低停顿时间,适用于响应时间敏感的Web应用。但存在内存碎片问题,需通过
-XX:+UseCMSCompactAtFullCollection参数在Full GC时触发内存整理。 - G1(Garbage-First):面向大内存(>4GB)场景,通过Region分区实现可预测的停顿时间。其混合回收(Mixed GC)机制同时处理年轻代与老年代对象,适合高吞吐量需求。
建议:根据业务特性选择回收器,例如电商系统优先G1,而实时交易系统可考虑ZGC(JDK11+)。
2. 类加载机制深度解析
问题示例:”双亲委派模型的作用是什么?如何破坏双亲委派?”
- 双亲委派模型:类加载器自底向上检查是否已加载类,避免重复加载与安全冲突(如防止
java.lang.String被自定义类覆盖)。 - 破坏双亲委派:通过重写
ClassLoader.loadClass()方法或使用线程上下文类加载器(如JDBC驱动加载)。Spring的ClassPathXmlApplicationContext即通过此机制加载用户自定义Bean。
代码示例:public class CustomClassLoader extends ClassLoader {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {byte[] bytes = loadBytesFromFile(name); // 自定义类加载逻辑return defineClass(name, bytes, 0, bytes.length);}}
二、并发编程与多线程
1. 线程池配置与优化
高频考点:”如何合理配置线程池参数?ThreadPoolExecutor的拒绝策略有哪些?”
- 核心参数:
corePoolSize:核心线程数,建议设为NCPU * UCPU * (1 + W/C)(NCPU为CPU核心数,UCPU为目标CPU利用率,W为等待时间,C为计算时间)。maximumPoolSize:最大线程数,需结合任务类型(IO密集型可设为2*NCPU)。keepAliveTime:非核心线程空闲存活时间。
- 拒绝策略:
AbortPolicy(默认):抛出RejectedExecutionException。CallerRunsPolicy:由提交任务的线程直接执行。
实践建议:使用Executors.newFixedThreadPool()时需注意无界队列可能导致OOM,推荐显式创建ThreadPoolExecutor。
2. 并发工具类实战
问题示例:”CountDownLatch与CyclicBarrier的区别是什么?”
- CountDownLatch:单向等待,适用于主线程等待多个子任务完成(如并行测试)。
CountDownLatch latch = new CountDownLatch(3);for (int i = 0; i < 3; i++) {new Thread(() -> {System.out.println("Task completed");latch.countDown();}).start();}latch.await(); // 主线程阻塞
- CyclicBarrier:循环等待,适用于多线程分阶段协作(如游戏回合制)。
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All ready"));new Thread(() -> {try {barrier.await(); // 等待其他线程} catch (Exception e) {}}).start();
三、Spring框架核心
1. IoC与AOP实现原理
典型问题:”Spring如何解决循环依赖?AOP的动态代理方式有哪些?”
- 循环依赖处理:Spring通过三级缓存(
singletonFactories、earlySingletonObjects、singletonObjects)解决构造器循环依赖,但仅支持单例作用域的setter注入。 - AOP代理:
- JDK动态代理:基于接口,通过
Proxy.newProxyInstance()生成代理类。 - CGLIB代理:基于继承,适用于无接口类,需注意
final方法无法代理。
代码示例:// JDK动态代理public class LoggingProxy implements InvocationHandler {private Object target;public Object invoke(Object proxy, Method method, Object[] args) {System.out.println("Before method: " + method.getName());return method.invoke(target, args);}}
- JDK动态代理:基于接口,通过
2. 事务传播行为
高频考点:”PROPAGATION_REQUIRED与PROPAGATION_REQUIRES_NEW的区别?”
- REQUIRED:加入当前事务,若不存在则新建(默认行为)。
- REQUIRES_NEW:总是新建事务,挂起当前事务(适用于日志记录等独立操作)。
配置示例:@Transactional(propagation = Propagation.REQUIRES_NEW)public void independentOperation() {// 独立事务逻辑}
四、数据库与SQL优化
1. 索引失效场景
问题示例:”哪些情况下MySQL索引会失效?”
- 隐式类型转换:如
where numeric_column = '123'。 - 使用函数:
where DATE(create_time) = '2021-01-01'。 - OR条件:除非所有列均有索引,否则可能全表扫描。
优化建议:使用EXPLAIN分析执行计划,重点关注type列(应避免ALL全表扫描)。
2. 事务隔离级别
典型问题:”READ COMMITTED与REPEATABLE READ的区别?MySQL默认级别是什么?”
- READ COMMITTED:允许不可重复读,但避免脏读(Oracle默认)。
- REPEATABLE READ:避免不可重复读,但可能幻读(MySQL默认,通过MVCC与Next-Key锁解决)。
设置方式:SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
五、分布式与微服务
1. 分布式锁实现
高频考点:”如何用Redis实现分布式锁?需要注意哪些问题?”
- Redisson方案:
RLock lock = redissonClient.getLock("order_lock");lock.lock(); // 默认30秒超时try {// 业务逻辑} finally {lock.unlock();}
- 注意事项:
- 需设置超时时间防止死锁。
- 使用
SETNX + EXPIRE原子命令(Redis 2.6.12+支持SET key value NX EX 30)。
2. 微服务注册中心对比
问题示例:”Eureka与Nacos的核心差异是什么?”
- Eureka:AP架构(高可用优先),适用于Spring Cloud生态。
- Nacos:支持CP/AP模式切换,集成配置中心功能,适合多语言环境。
选型建议:中小型项目可选Eureka,大型分布式系统推荐Nacos。
六、备考策略与建议
- 源码阅读:重点掌握
HashMap、ConcurrentHashMap、AQS等核心类源码。 - 项目复盘:将实际项目中的技术难点(如分布式事务、高并发优化)与面试题结合。
- 模拟面试:通过LeetCode(算法)、牛客网(Java专题)进行针对性练习。
结语:2021年Java面试更注重底层原理与工程实践能力,建议开发者在掌握基础的同时,深入理解技术选型的背景与权衡。通过系统性复习与实战演练,可显著提升面试成功率。