今日学习总结
今天深入研究了JVM类加载机制中的双亲委派模型和内存区域划分,并完成了二叉树中序遍历的算法练习。以下是详细的技术复盘:
---
1. JVM核心机制进阶
##### 双亲委派模型(三层级防御体系)
**工作流程**:
1. 子加载器收到请求后立即委派父加载器
2. 父加载器检查缓存(findLoadedClass)
3. 父加载器尝试加载(findClass)
4. 所有父加载器失败后,子加载器才自行加载
**设计优势**:
- 安全性保障:防止核心API被篡改(如自定义java.lang.String)
- 资源复用:避免重复加载消耗内存
- 结构清晰:明确的层级责任划分
**破坏场景**:
- SPI机制(JDBC驱动加载)
- OSGi模块化热部署
- 热代码替换(Debug模式)
**高频考点**:
```java
// 自定义类加载器关键代码
protected Class<?> loadClass(String name, boolean resolve) {
synchronized (getClassLoadingLock(name)) {
// 1.检查已加载类
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
// 2.优先委派父加载器
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {}
if (c == null) {
// 3.自行加载
c = findClass(name);
}
}
return c;
}
}
```
##### JVM内存区域(运行时数据区)
| 区域 | 线程共享 | 存储内容 | 异常类型 | 配置参数 |
|------|----------|----------|----------|----------|
| 方法区 | 共享 | 类信息/常量/静态变量 | OOM | -XX:MetaspaceSize |
| 堆 | 共享 | 对象实例 | OOM | -Xmx/-Xms |
| 虚拟机栈 | 私有 | 栈帧/局部变量表 | StackOverflow | -Xss |
| 本地方法栈 | 私有 | Native方法 | StackOverflow | - |
| 程序计数器 | 私有 | 字节码行号 | 无 | - |
**重点辨析**:
- 方法区演进:PermGen→Metaspace(JDK8)
- 堆内存分代:Young/Old区比例(-XX:NewRatio)
- 栈帧结构:局部变量表/操作数栈/动态链接/返回地址
---
2. 算法实战:二叉树中序遍历
##### 递归解法精析
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
dfs(root, res); // 开启递归
return res;
}
private void dfs(TreeNode node, List<Integer> res) {
// 递归终止条件
if (node == null) return;
dfs(node.left, res); // 左子树递归
res.add(node.val); // 访问根节点
dfs(node.right, res); // 右子树递归
}
}
##### 迭代解法(显式栈模拟)
```java
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> stack = new ArrayDeque<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left; // 深度压栈左节点
}
cur = stack.pop();
res.add(cur.val); // 左-根-右顺序访问
cur = cur.right; // 转向右子树
}
return res;
}