- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
Java中高级工程师面试题及答案
一、JVM与内存模型(高频)
问:JVM内存区域怎么划分?永久代和元空间有啥区别?实际开发中遇到过元空间相关的问题吗?
答:JVM内存分线程私有(程序计数器、虚拟机栈、本地方法栈)和线程共享(堆、方法区)。程序计数器是唯一不会OOM的区域,虚拟机栈存方法栈帧(局部变量、操作数栈),堆是对象存储核心(分年轻代Eden/S0/S1、老年代),方法区存类信息、常量、静态变量。
永久代是JDK1.7及之前的说法,属于方法区的实现,用的是JVM内存;元空间是JDK1.8替换永久代的,用的是本地内存(系统内存)。实际项目中遇到过元空间OOM,是因为大量动态生成类(比如用CGLIB代理、反射生成类),没及时回收,后来调整了-XX:MetaspaceSize和-XX:MaxMetaspaceSize,并优化了代理类的缓存策略才解决。
问:CMS和G1垃圾收集器的核心区别是什么?如果项目是高并发接口,选哪个更合适?
答:CMS是“并发标记-清除”,核心是“并发”——标记和清除阶段尽量不阻塞用户线程,缺点是会产生内存碎片,老年代满了会触发FullGC(卡顿严重)。G1是“区域化分代收集”,把堆分成多个Region,能实现可预测的停顿(通过-XX:MaxGCPauseMillis设置),还能跨代收集,内存碎片也少。
高并发接口(比如秒杀、支付)对停顿敏感,选G1更合适。之前项目做支付网关,用CMS时偶尔会因FullGC卡1-2秒,换成G1后,把最大停顿设为200ms,线上基本没出现过因GC导致的超时。
二、并发编程(核心)
问:线程池的核心参数有哪些?实际工作中怎么设置核心线程数和最大线程数?
答:核心参数是:核心线程数(corePoolSize)、最大线程数(maximumPoolSize)、空闲线程存活时间(keepAliveTime)、阻塞队列(workQueue)、拒绝策略(handler)。
设置线程数要看业务类型:IO密集型(比如调用HTTP接口、查数据库),线程经常等IO结果,核心线程数可以设为CPU核心数*2(比如8核CPU设16);CPU密集型(比如大数据计算、循环处理),线程一直占CPU,核心线程数设为CPU核心数+1(避免线程切换损耗)。之前做报表计算(CPU密集),8核CPU设了9个核心线程,比设16的时候吞吐量高20%。
问:volatile关键字能保证原子性吗?举个实际场景说明它的作用。
答:不能保证原子性,比如i++这种操作,volatile只能保证可见性(一个线程改了,其他线程马上看到)和禁止指令重排序,原子性得靠synchronized或Atomic类。
实际场景:比如项目里的“服务状态开关”,用volatile修饰booleanisRunning=true,主线程把isRunning改成false,工作线程能立刻感知到并停止循环,避免线程“看不到修改”导致的死循环。如果不加volatile,工作线程可能一直读缓存里的true,永远不停止。
问:ConcurrentHashMap在JDK1.7和1.8的实现有啥区别?实际用的时候要注意什么?
答:1.7是“分段锁(Segment)”,每个Segment是个小HashMap,锁只锁一个Segment,并发度是Segment数量(默认16);1.8改成了“CAS+synchronized”,锁的是链表头/红黑树根节点,粒度更细,并发性能更好,还把链表转红黑树的阈值从16改成了8(因为泊松分布计算,链表长度8的概率极低,改成红黑树更高效)。
注意点:1.8虽然线程安全,但computeIfAbsent这种方法在高并发下可能有延迟,之前做缓存的时候,用它存热点数据,偶尔会出现同一key多次计算的情况,后来加了双重检查才解决。
三、Spring核心(必问)
问:SpringBean的生命周期?实际开发中怎么自定义Bean的初始化逻辑?
答:大概流程是:实例化(new对象)→属性注入(setter/构造器注入)→初始化前(BeanPostProcessor的postProcessBeforeInitialization)→初始化(InitializingBean的afterPropertiesSet、@PostConstruct、XML里的init-method)→初始化后(BeanPostProcessor的postProcessAfterInitialization)→就绪
文档评论(0)