Java · 02 核心能力
语言真正不同的地方:JVM、并发模型、内存与性能直觉。目标是 够交付、够排障,不当调优百科。
1. JVM 与运行机制
底线(必须建立的图景)
.java → 编译 → .class(字节码)→ 类加载 → JVM 执行
↓
堆(对象) / 栈(帧、局部变量) / 元空间(类元数据)- 写出问题前先分清:是 业务逻辑错了,还是 运行时(内存 / 线程 / GC) 出问题
- Full GC / OOM 出现时知道:看堆?看元空间?看直接内存?看线程栈?
我刻意不追求
- 把每一种垃圾收集器参数背成百科
- 没有线上证据就谈「调优专家」
判断
面试能画图、线上能定位,就够支撑中小交付;更深的调优跟 具体故障 走。
相关:后端问题 · 性能
2. 并发模型
Java 并发主流是 线程 + 共享内存(重,但匹配企业共享状态多的现实)。
我常用的几块
| 工具 | 解决什么 | 注意 |
|---|---|---|
synchronized / Lock | 互斥 | 锁粒度;避免在锁内调远程 |
volatile | 可见性与有序 | 不保证 i++ 这类复合操作原子性 |
线程池 ExecutorService | 资源边界 | 别裸 new Thread;队列与拒绝策略要想清楚 |
ConcurrentHashMap 等 | 并发容器 | 仍要理解「复合操作」是否原子 |
| 虚拟线程(新版本) | 大量阻塞 IO | 共享可变状态纪律不能松 |
和其它语言比
| 语言 | 模型 | 对我的启发 |
|---|---|---|
| Java | 线程 + 共享内存 | 默认企业路径 |
| Go | Goroutine + Channel | 通信胜共享的思路可借鉴 |
| Node | 事件循环 | 单线程别堵;重活要迁出 |
我的用法
- 业务默认:一请求一处理线程(容器线程)+ 必要时有界线程池
- 复杂编排(如 AI 生成任务):队列 + 状态机 + 重试,而不是在接口里狂开线程
- 共享可变状态能少则少;必须共享就明确锁或单写多读
相关:后端问题 · 并发
3. 内存与性能直觉
现象 → 优先怀疑
| 现象 | 优先怀疑 | 第一步 |
|---|---|---|
| 堆持续涨、频繁 Full GC | 泄漏、缓存无界、大对象滞留 | 堆 dump / 看缓存 key 数量 |
| CPU 高、RT 差 | 锁竞争、热循环、疯狂序列化/正则 | 采样线程栈 |
| 偶发超时 | 线程池打满、连接池耗尽、下游慢 | 看池队列与下游 RT |
| 启动很慢 | 组件扫描过大、依赖过重、本机 IO | 精简自动配置、看启动报告 |
原则
- 先架构与 IO,再抠微语法
- 绝对性能对多数业务系统「够用」;瓶颈常在库、网络、错误重试、N+1 SQL
- 缓存是把双刃剑:没有失效策略的缓存 = 定时炸弹
4. 适合什么 / 不适合什么
| 适合 | 不适合(对我而言) |
|---|---|
| 中长期业务系统、强协作 | 一天验证完的 AI 脚本(用 Python) |
| 事务、规范、中间件集成 | 只图写起来爽的个人小工具 |
| 招聘友好、可维护存量 | 为了「新语言」重写已稳定域 |
| MES / CRM / 内容生产状态机 | 纯 CPU 数值计算尖端场景 |
边界感
- 需要 强事务 + 多人协作 + 长期演进 → Java
- 需要 快速试模型 / 批处理文件 → Python 旁路,结果回写 Java
- 需要 和前端同构的 BFF / 桌面本地服务 → Node(TS)
下一篇:03 框架与生态