Java 源码不会直接交给 CPU 执行。开发阶段使用 JDK 编译源码,运行阶段由 JVM 加载字节码、管理内存和线程,并通过解释执行与即时编译运行热点代码。

JDK、JRE 与 JVM

名称 作用
JDK 编译器、调试器、打包工具和运行环境
JRE 运行 Java 程序所需组件的传统集合概念
JVM 执行字节码、管理内存、线程和垃圾回收

现代 JDK 已包含运行程序所需能力,部署时也可用 jlink 创建按需运行时,不必机械地寻找一个单独 JRE 安装包。

程序启动流程

1
2
3
4
5
6
7
8
9
10
java -jar app.jar
-> 操作系统启动 JVM 进程
-> JVM 创建运行时内存区域
-> 类加载器加载入口类及依赖
-> 校验、准备、解析、初始化类
-> 调用 main 方法
-> Spring 创建 ApplicationContext
-> 扫描并创建 Bean
-> 启动嵌入式 Web Server
-> 监听端口等待请求

类通常先解释执行;热点方法经过分析后可由 JIT 编译成本地机器码。JIT 是运行时优化,不是把整个程序在启动前一次性编译完。

Spring Boot 请求链路

1
2
3
4
5
6
7
8
9
10
HTTP Connector
-> 容器线程池
-> Filter
-> DispatcherServlet
-> Interceptor
-> Controller
-> Service
-> Repository
-> 数据库或外部服务
-> 序列化并返回响应

常见 Servlet Web 应用通常让一个请求占用一个工作线程,直到同步处理结束。线程池耗尽后,请求会排队或被拒绝,所以慢 SQL 和无超时的外部调用会迅速放大故障。

IoC、DI 与 AOP

  • IoC(控制反转):对象创建和组装交给容器管理。
  • DI(依赖注入):容器把对象需要的依赖提供给它。
  • AOP(面向切面编程):在方法调用周围加入事务、日志、权限等横切逻辑。
1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class OrderService {
private final OrderRepository orders;

public OrderService(OrderRepository orders) {
this.orders = orders;
}

@Transactional
public void create(Order order) {
orders.save(order);
}
}

@Transactional 常通过代理拦截方法调用。类内部直接调用自身方法可能绕过代理;异常类型、传播行为和数据库能力也会影响是否回滚。

内存与并发

每个线程有自己的栈,多个线程共享堆中的对象。共享可变对象需要锁、并发容器或原子类保护。线程不是越多越好:线程会占用栈空间,并增加上下文切换和下游压力。

Java 服务过载时常见链路:

1
2
慢查询 -> 请求线程长期占用 -> 线程池排队
-> 超时增加 -> 重试放大流量 -> 内存和 CPU 上升

应同时限制 Web 线程池、数据库连接池、外部调用并发和队列长度,并提供超时、拒绝、降级与监控。

延伸阅读

站内搜索

没有找到内容!