diff --git a/Java/01Java语言基础/01 Java基础.md b/Java/01Java语言基础/01 Java基础.md index e896fb23..a92e0691 100644 --- a/Java/01Java语言基础/01 Java基础.md +++ b/Java/01Java语言基础/01 Java基础.md @@ -2,6 +2,7 @@ - [Java 基础](#java-基础) - [0 引言](#0-引言) + - [如何快速掌握一门语言](#如何快速掌握一门语言) - [Java特性和优势](#java特性和优势) - [JDK、JRE和JVM](#jdkjre和jvm) - [编译和解释](#编译和解释) @@ -47,6 +48,16 @@ > 本笔记主要介绍java提供的语言级别的支持,不包括标准库的内容。 +### 如何快速掌握一门语言 + +一个语言应该包括以下几个部分 + +* 语言基础:数据类型和变量、控制流程、数据结构、函数、面向对象、其他 +* 标准工具库:数学、日期、字符串、系统、序列化等 +* 内置高阶库:文件IO、网络编程、并发编程 +* 生态库:Web框架、客户端、分布式 +* 编译原理:虚拟机、内存管理、类加载等 +* 问题排查和性能优化:产业实践的经验 ### Java特性和优势 diff --git a/Java/02Java标准库/01 Object类.md b/Java/02Java标准工具库/01 Object类.md similarity index 100% rename from Java/02Java标准库/01 Object类.md rename to Java/02Java标准工具库/01 Object类.md diff --git a/Java/02Java标准库/02 包装器类.md b/Java/02Java标准工具库/02 包装器类.md similarity index 100% rename from Java/02Java标准库/02 包装器类.md rename to Java/02Java标准工具库/02 包装器类.md diff --git a/Java/02Java标准库/03 String类.md b/Java/02Java标准工具库/03 String类.md similarity index 100% rename from Java/02Java标准库/03 String类.md rename to Java/02Java标准工具库/03 String类.md diff --git a/Java/02Java标准库/04 数学计算.md b/Java/02Java标准工具库/04 数学计算.md similarity index 100% rename from Java/02Java标准库/04 数学计算.md rename to Java/02Java标准工具库/04 数学计算.md diff --git a/Java/02Java标准库/05 日期时间.md b/Java/02Java标准工具库/05 日期时间.md similarity index 100% rename from Java/02Java标准库/05 日期时间.md rename to Java/02Java标准工具库/05 日期时间.md diff --git a/Java/02Java标准库/06 Scanner.md b/Java/02Java标准工具库/06 Scanner.md similarity index 100% rename from Java/02Java标准库/06 Scanner.md rename to Java/02Java标准工具库/06 Scanner.md diff --git a/Java/02Java标准库/07 正则表达式.md b/Java/02Java标准工具库/07 正则表达式.md similarity index 100% rename from Java/02Java标准库/07 正则表达式.md rename to Java/02Java标准工具库/07 正则表达式.md diff --git a/Java/02Java标准库/08 随机数Random.md b/Java/02Java标准工具库/08 随机数Random.md similarity index 100% rename from Java/02Java标准库/08 随机数Random.md rename to Java/02Java标准工具库/08 随机数Random.md diff --git a/Java/02Java标准库/09 System类.md b/Java/02Java标准工具库/09 System类.md similarity index 100% rename from Java/02Java标准库/09 System类.md rename to Java/02Java标准工具库/09 System类.md diff --git a/Java/02Java标准库/11 Unsafe类.md b/Java/02Java标准工具库/11 Unsafe类.md similarity index 100% rename from Java/02Java标准库/11 Unsafe类.md rename to Java/02Java标准工具库/11 Unsafe类.md diff --git a/Java/02Java标准库/image/2022-07-12-11-07-56.png b/Java/02Java标准工具库/image/2022-07-12-11-07-56.png similarity index 100% rename from Java/02Java标准库/image/2022-07-12-11-07-56.png rename to Java/02Java标准工具库/image/2022-07-12-11-07-56.png diff --git a/Java/02Java标准库/image/2022-11-26-17-31-29.png b/Java/02Java标准工具库/image/2022-11-26-17-31-29.png similarity index 100% rename from Java/02Java标准库/image/2022-11-26-17-31-29.png rename to Java/02Java标准工具库/image/2022-11-26-17-31-29.png diff --git a/Java/02Java标准库/image/2022-11-26-18-03-55.png b/Java/02Java标准工具库/image/2022-11-26-18-03-55.png similarity index 100% rename from Java/02Java标准库/image/2022-11-26-18-03-55.png rename to Java/02Java标准工具库/image/2022-11-26-18-03-55.png diff --git a/Java/02Java标准库/image/2022-11-26-19-20-23.png b/Java/02Java标准工具库/image/2022-11-26-19-20-23.png similarity index 100% rename from Java/02Java标准库/image/2022-11-26-19-20-23.png rename to Java/02Java标准工具库/image/2022-11-26-19-20-23.png diff --git a/Java/02Java标准库/image/2022-11-26-19-31-24.png b/Java/02Java标准工具库/image/2022-11-26-19-31-24.png similarity index 100% rename from Java/02Java标准库/image/2022-11-26-19-31-24.png rename to Java/02Java标准工具库/image/2022-11-26-19-31-24.png diff --git a/Java/02Java标准库/image/2022-11-26-19-40-09.png b/Java/02Java标准工具库/image/2022-11-26-19-40-09.png similarity index 100% rename from Java/02Java标准库/image/2022-11-26-19-40-09.png rename to Java/02Java标准工具库/image/2022-11-26-19-40-09.png diff --git a/Java/02Java标准库/image/2022-11-26-19-40-59.png b/Java/02Java标准工具库/image/2022-11-26-19-40-59.png similarity index 100% rename from Java/02Java标准库/image/2022-11-26-19-40-59.png rename to Java/02Java标准工具库/image/2022-11-26-19-40-59.png diff --git a/Java/02Java标准库/image/2022-11-26-20-24-47.png b/Java/02Java标准工具库/image/2022-11-26-20-24-47.png similarity index 100% rename from Java/02Java标准库/image/2022-11-26-20-24-47.png rename to Java/02Java标准工具库/image/2022-11-26-20-24-47.png diff --git a/Java/02Java标准库/image/2023-03-13-10-53-12.png b/Java/02Java标准工具库/image/2023-03-13-10-53-12.png similarity index 100% rename from Java/02Java标准库/image/2023-03-13-10-53-12.png rename to Java/02Java标准工具库/image/2023-03-13-10-53-12.png diff --git a/Java/02Java标准库/image/2023-03-13-10-54-08.png b/Java/02Java标准工具库/image/2023-03-13-10-54-08.png similarity index 100% rename from Java/02Java标准库/image/2023-03-13-10-54-08.png rename to Java/02Java标准工具库/image/2023-03-13-10-54-08.png diff --git a/Java/03Java集合类/01 Java数据结构.md b/Java/03Java标准集合类/01 Java数据结构.md similarity index 100% rename from Java/03Java集合类/01 Java数据结构.md rename to Java/03Java标准集合类/01 Java数据结构.md diff --git a/Java/03Java集合类/01 集合底层结构.md b/Java/03Java标准集合类/01 集合底层结构.md similarity index 100% rename from Java/03Java集合类/01 集合底层结构.md rename to Java/03Java标准集合类/01 集合底层结构.md diff --git a/Java/03Java集合类/02 JavaCollection.md b/Java/03Java标准集合类/02 JavaCollection.md similarity index 100% rename from Java/03Java集合类/02 JavaCollection.md rename to Java/03Java标准集合类/02 JavaCollection.md diff --git a/Java/03Java集合类/03 List.md b/Java/03Java标准集合类/03 List.md similarity index 100% rename from Java/03Java集合类/03 List.md rename to Java/03Java标准集合类/03 List.md diff --git a/Java/03Java集合类/04 Queue.md b/Java/03Java标准集合类/04 Queue.md similarity index 100% rename from Java/03Java集合类/04 Queue.md rename to Java/03Java标准集合类/04 Queue.md diff --git a/Java/03Java集合类/05 Set.md b/Java/03Java标准集合类/05 Set.md similarity index 100% rename from Java/03Java集合类/05 Set.md rename to Java/03Java标准集合类/05 Set.md diff --git a/Java/03Java集合类/06 Map.md b/Java/03Java标准集合类/06 Map.md similarity index 100% rename from Java/03Java集合类/06 Map.md rename to Java/03Java标准集合类/06 Map.md diff --git a/Java/03Java集合类/07 Iterable&Ieterator.md b/Java/03Java标准集合类/07 Iterable&Ieterator.md similarity index 100% rename from Java/03Java集合类/07 Iterable&Ieterator.md rename to Java/03Java标准集合类/07 Iterable&Ieterator.md diff --git a/Java/03Java集合类/08 Comparable&Comparator.md b/Java/03Java标准集合类/08 Comparable&Comparator.md similarity index 100% rename from Java/03Java集合类/08 Comparable&Comparator.md rename to Java/03Java标准集合类/08 Comparable&Comparator.md diff --git a/Java/03Java集合类/09 Sort.md b/Java/03Java标准集合类/09 Sort.md similarity index 100% rename from Java/03Java集合类/09 Sort.md rename to Java/03Java标准集合类/09 Sort.md diff --git a/Java/03Java集合类/09 Stream.md b/Java/03Java标准集合类/09 Stream.md similarity index 100% rename from Java/03Java集合类/09 Stream.md rename to Java/03Java标准集合类/09 Stream.md diff --git a/Java/03Java集合类/image/2022-11-08-10-51-54.png b/Java/03Java标准集合类/image/2022-11-08-10-51-54.png similarity index 100% rename from Java/03Java集合类/image/2022-11-08-10-51-54.png rename to Java/03Java标准集合类/image/2022-11-08-10-51-54.png diff --git a/Java/03Java集合类/image/2022-11-08-10-54-19.png b/Java/03Java标准集合类/image/2022-11-08-10-54-19.png similarity index 100% rename from Java/03Java集合类/image/2022-11-08-10-54-19.png rename to Java/03Java标准集合类/image/2022-11-08-10-54-19.png diff --git a/Java/03Java集合类/image/2022-12-04-22-09-27.png b/Java/03Java标准集合类/image/2022-12-04-22-09-27.png similarity index 100% rename from Java/03Java集合类/image/2022-12-04-22-09-27.png rename to Java/03Java标准集合类/image/2022-12-04-22-09-27.png diff --git a/Java/03Java集合类/image/2022-12-04-22-17-09.png b/Java/03Java标准集合类/image/2022-12-04-22-17-09.png similarity index 100% rename from Java/03Java集合类/image/2022-12-04-22-17-09.png rename to Java/03Java标准集合类/image/2022-12-04-22-17-09.png diff --git a/Java/03Java集合类/image/2022-12-04-22-20-35.png b/Java/03Java标准集合类/image/2022-12-04-22-20-35.png similarity index 100% rename from Java/03Java集合类/image/2022-12-04-22-20-35.png rename to Java/03Java标准集合类/image/2022-12-04-22-20-35.png diff --git a/Java/03Java集合类/image/2022-12-04-22-53-11.png b/Java/03Java标准集合类/image/2022-12-04-22-53-11.png similarity index 100% rename from Java/03Java集合类/image/2022-12-04-22-53-11.png rename to Java/03Java标准集合类/image/2022-12-04-22-53-11.png diff --git a/Java/03Java集合类/image/2022-12-15-16-54-49.png b/Java/03Java标准集合类/image/2022-12-15-16-54-49.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-16-54-49.png rename to Java/03Java标准集合类/image/2022-12-15-16-54-49.png diff --git a/Java/03Java集合类/image/2022-12-15-16-54-56.png b/Java/03Java标准集合类/image/2022-12-15-16-54-56.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-16-54-56.png rename to Java/03Java标准集合类/image/2022-12-15-16-54-56.png diff --git a/Java/03Java集合类/image/2022-12-15-16-55-23.png b/Java/03Java标准集合类/image/2022-12-15-16-55-23.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-16-55-23.png rename to Java/03Java标准集合类/image/2022-12-15-16-55-23.png diff --git a/Java/03Java集合类/image/2022-12-15-17-11-05.png b/Java/03Java标准集合类/image/2022-12-15-17-11-05.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-17-11-05.png rename to Java/03Java标准集合类/image/2022-12-15-17-11-05.png diff --git a/Java/03Java集合类/image/2022-12-15-17-14-17.png b/Java/03Java标准集合类/image/2022-12-15-17-14-17.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-17-14-17.png rename to Java/03Java标准集合类/image/2022-12-15-17-14-17.png diff --git a/Java/03Java集合类/image/2022-12-15-19-08-19.png b/Java/03Java标准集合类/image/2022-12-15-19-08-19.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-19-08-19.png rename to Java/03Java标准集合类/image/2022-12-15-19-08-19.png diff --git a/Java/03Java集合类/image/2022-12-15-19-08-34.png b/Java/03Java标准集合类/image/2022-12-15-19-08-34.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-19-08-34.png rename to Java/03Java标准集合类/image/2022-12-15-19-08-34.png diff --git a/Java/03Java集合类/image/2022-12-15-19-16-20.png b/Java/03Java标准集合类/image/2022-12-15-19-16-20.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-19-16-20.png rename to Java/03Java标准集合类/image/2022-12-15-19-16-20.png diff --git a/Java/03Java集合类/image/2022-12-15-19-17-09.png b/Java/03Java标准集合类/image/2022-12-15-19-17-09.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-19-17-09.png rename to Java/03Java标准集合类/image/2022-12-15-19-17-09.png diff --git a/Java/03Java集合类/image/2022-12-15-19-28-47.png b/Java/03Java标准集合类/image/2022-12-15-19-28-47.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-19-28-47.png rename to Java/03Java标准集合类/image/2022-12-15-19-28-47.png diff --git a/Java/03Java集合类/image/2022-12-15-19-35-52.png b/Java/03Java标准集合类/image/2022-12-15-19-35-52.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-19-35-52.png rename to Java/03Java标准集合类/image/2022-12-15-19-35-52.png diff --git a/Java/03Java集合类/image/2022-12-15-19-38-24.png b/Java/03Java标准集合类/image/2022-12-15-19-38-24.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-19-38-24.png rename to Java/03Java标准集合类/image/2022-12-15-19-38-24.png diff --git a/Java/03Java集合类/image/2022-12-15-19-39-03.png b/Java/03Java标准集合类/image/2022-12-15-19-39-03.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-19-39-03.png rename to Java/03Java标准集合类/image/2022-12-15-19-39-03.png diff --git a/Java/03Java集合类/image/2022-12-15-20-19-36.png b/Java/03Java标准集合类/image/2022-12-15-20-19-36.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-20-19-36.png rename to Java/03Java标准集合类/image/2022-12-15-20-19-36.png diff --git a/Java/03Java集合类/image/2022-12-15-21-12-52.png b/Java/03Java标准集合类/image/2022-12-15-21-12-52.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-21-12-52.png rename to Java/03Java标准集合类/image/2022-12-15-21-12-52.png diff --git a/Java/03Java集合类/image/2022-12-15-21-53-10.png b/Java/03Java标准集合类/image/2022-12-15-21-53-10.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-21-53-10.png rename to Java/03Java标准集合类/image/2022-12-15-21-53-10.png diff --git a/Java/03Java集合类/image/2022-12-15-22-45-56.png b/Java/03Java标准集合类/image/2022-12-15-22-45-56.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-22-45-56.png rename to Java/03Java标准集合类/image/2022-12-15-22-45-56.png diff --git a/Java/03Java集合类/image/2022-12-15-22-46-12.png b/Java/03Java标准集合类/image/2022-12-15-22-46-12.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-22-46-12.png rename to Java/03Java标准集合类/image/2022-12-15-22-46-12.png diff --git a/Java/03Java集合类/image/2022-12-15-22-46-59.png b/Java/03Java标准集合类/image/2022-12-15-22-46-59.png similarity index 100% rename from Java/03Java集合类/image/2022-12-15-22-46-59.png rename to Java/03Java标准集合类/image/2022-12-15-22-46-59.png diff --git a/Java/05JavaIO与网络编程/01 Java 标准IO.md b/Java/05Java文件IO与网络编程/01 Java 标准IO.md similarity index 100% rename from Java/05JavaIO与网络编程/01 Java 标准IO.md rename to Java/05Java文件IO与网络编程/01 Java 标准IO.md diff --git a/Java/05JavaIO与网络编程/02 Java NIO.md b/Java/05Java文件IO与网络编程/02 Java NIO.md similarity index 100% rename from Java/05JavaIO与网络编程/02 Java NIO.md rename to Java/05Java文件IO与网络编程/02 Java NIO.md diff --git a/Java/05JavaIO与网络编程/03 Java IO文件.md b/Java/05Java文件IO与网络编程/03 Java IO文件.md similarity index 100% rename from Java/05JavaIO与网络编程/03 Java IO文件.md rename to Java/05Java文件IO与网络编程/03 Java IO文件.md diff --git a/Java/05JavaIO与网络编程/04 Java IO对象.md b/Java/05Java文件IO与网络编程/04 Java IO对象.md similarity index 100% rename from Java/05JavaIO与网络编程/04 Java IO对象.md rename to Java/05Java文件IO与网络编程/04 Java IO对象.md diff --git a/Java/05JavaIO与网络编程/05 Java IO网络.md b/Java/05Java文件IO与网络编程/05 Java IO网络.md similarity index 100% rename from Java/05JavaIO与网络编程/05 Java IO网络.md rename to Java/05Java文件IO与网络编程/05 Java IO网络.md diff --git a/Java/05JavaIO与网络编程/image/2022-11-08-10-51-54.png b/Java/05Java文件IO与网络编程/image/2022-11-08-10-51-54.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-08-10-51-54.png rename to Java/05Java文件IO与网络编程/image/2022-11-08-10-51-54.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-08-10-54-19.png b/Java/05Java文件IO与网络编程/image/2022-11-08-10-54-19.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-08-10-54-19.png rename to Java/05Java文件IO与网络编程/image/2022-11-08-10-54-19.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-26-17-31-29.png b/Java/05Java文件IO与网络编程/image/2022-11-26-17-31-29.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-26-17-31-29.png rename to Java/05Java文件IO与网络编程/image/2022-11-26-17-31-29.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-26-18-03-55.png b/Java/05Java文件IO与网络编程/image/2022-11-26-18-03-55.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-26-18-03-55.png rename to Java/05Java文件IO与网络编程/image/2022-11-26-18-03-55.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-26-19-20-23.png b/Java/05Java文件IO与网络编程/image/2022-11-26-19-20-23.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-26-19-20-23.png rename to Java/05Java文件IO与网络编程/image/2022-11-26-19-20-23.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-26-19-31-24.png b/Java/05Java文件IO与网络编程/image/2022-11-26-19-31-24.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-26-19-31-24.png rename to Java/05Java文件IO与网络编程/image/2022-11-26-19-31-24.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-26-19-40-09.png b/Java/05Java文件IO与网络编程/image/2022-11-26-19-40-09.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-26-19-40-09.png rename to Java/05Java文件IO与网络编程/image/2022-11-26-19-40-09.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-26-19-40-59.png b/Java/05Java文件IO与网络编程/image/2022-11-26-19-40-59.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-26-19-40-59.png rename to Java/05Java文件IO与网络编程/image/2022-11-26-19-40-59.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-26-20-24-47.png b/Java/05Java文件IO与网络编程/image/2022-11-26-20-24-47.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-26-20-24-47.png rename to Java/05Java文件IO与网络编程/image/2022-11-26-20-24-47.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-27-00-08-19.png b/Java/05Java文件IO与网络编程/image/2022-11-27-00-08-19.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-27-00-08-19.png rename to Java/05Java文件IO与网络编程/image/2022-11-27-00-08-19.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-27-00-33-15.png b/Java/05Java文件IO与网络编程/image/2022-11-27-00-33-15.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-27-00-33-15.png rename to Java/05Java文件IO与网络编程/image/2022-11-27-00-33-15.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-27-00-33-28.png b/Java/05Java文件IO与网络编程/image/2022-11-27-00-33-28.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-27-00-33-28.png rename to Java/05Java文件IO与网络编程/image/2022-11-27-00-33-28.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-27-00-33-35.png b/Java/05Java文件IO与网络编程/image/2022-11-27-00-33-35.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-27-00-33-35.png rename to Java/05Java文件IO与网络编程/image/2022-11-27-00-33-35.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-27-00-33-45.png b/Java/05Java文件IO与网络编程/image/2022-11-27-00-33-45.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-27-00-33-45.png rename to Java/05Java文件IO与网络编程/image/2022-11-27-00-33-45.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-27-00-33-59.png b/Java/05Java文件IO与网络编程/image/2022-11-27-00-33-59.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-27-00-33-59.png rename to Java/05Java文件IO与网络编程/image/2022-11-27-00-33-59.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-27-00-48-14.png b/Java/05Java文件IO与网络编程/image/2022-11-27-00-48-14.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-27-00-48-14.png rename to Java/05Java文件IO与网络编程/image/2022-11-27-00-48-14.png diff --git a/Java/05JavaIO与网络编程/image/2022-11-27-10-06-38.png b/Java/05Java文件IO与网络编程/image/2022-11-27-10-06-38.png similarity index 100% rename from Java/05JavaIO与网络编程/image/2022-11-27-10-06-38.png rename to Java/05Java文件IO与网络编程/image/2022-11-27-10-06-38.png diff --git a/Java/05JavaIO与网络编程/media/007ab35fabcc3bbba6b8e4defa4a37b1.png b/Java/05Java文件IO与网络编程/media/007ab35fabcc3bbba6b8e4defa4a37b1.png similarity index 100% rename from Java/05JavaIO与网络编程/media/007ab35fabcc3bbba6b8e4defa4a37b1.png rename to Java/05Java文件IO与网络编程/media/007ab35fabcc3bbba6b8e4defa4a37b1.png diff --git a/Java/05JavaIO与网络编程/media/028bef0da4c4d8440e13915a126df9ca.png b/Java/05Java文件IO与网络编程/media/028bef0da4c4d8440e13915a126df9ca.png similarity index 100% rename from Java/05JavaIO与网络编程/media/028bef0da4c4d8440e13915a126df9ca.png rename to Java/05Java文件IO与网络编程/media/028bef0da4c4d8440e13915a126df9ca.png diff --git a/Java/05JavaIO与网络编程/media/041cbc2e6105e1571f8c6570b651ab08.png b/Java/05Java文件IO与网络编程/media/041cbc2e6105e1571f8c6570b651ab08.png similarity index 100% rename from Java/05JavaIO与网络编程/media/041cbc2e6105e1571f8c6570b651ab08.png rename to Java/05Java文件IO与网络编程/media/041cbc2e6105e1571f8c6570b651ab08.png diff --git a/Java/05JavaIO与网络编程/media/065a723dabe70a4f55b1e194d9bbf4d2.png b/Java/05Java文件IO与网络编程/media/065a723dabe70a4f55b1e194d9bbf4d2.png similarity index 100% rename from Java/05JavaIO与网络编程/media/065a723dabe70a4f55b1e194d9bbf4d2.png rename to Java/05Java文件IO与网络编程/media/065a723dabe70a4f55b1e194d9bbf4d2.png diff --git a/Java/05JavaIO与网络编程/media/06e9b6a8836c9bea9aa0f49fc2b497e1.png b/Java/05Java文件IO与网络编程/media/06e9b6a8836c9bea9aa0f49fc2b497e1.png similarity index 100% rename from Java/05JavaIO与网络编程/media/06e9b6a8836c9bea9aa0f49fc2b497e1.png rename to Java/05Java文件IO与网络编程/media/06e9b6a8836c9bea9aa0f49fc2b497e1.png diff --git a/Java/05JavaIO与网络编程/media/0795fe05778f83e679a5f7fe70dc292d.png b/Java/05Java文件IO与网络编程/media/0795fe05778f83e679a5f7fe70dc292d.png similarity index 100% rename from Java/05JavaIO与网络编程/media/0795fe05778f83e679a5f7fe70dc292d.png rename to Java/05Java文件IO与网络编程/media/0795fe05778f83e679a5f7fe70dc292d.png diff --git a/Java/05JavaIO与网络编程/media/0a98a46c93fbd1041bdc163970fcad1f.png b/Java/05Java文件IO与网络编程/media/0a98a46c93fbd1041bdc163970fcad1f.png similarity index 100% rename from Java/05JavaIO与网络编程/media/0a98a46c93fbd1041bdc163970fcad1f.png rename to Java/05Java文件IO与网络编程/media/0a98a46c93fbd1041bdc163970fcad1f.png diff --git a/Java/05JavaIO与网络编程/media/0ed020222f07f3d0d0b405b20c9e4199.png b/Java/05Java文件IO与网络编程/media/0ed020222f07f3d0d0b405b20c9e4199.png similarity index 100% rename from Java/05JavaIO与网络编程/media/0ed020222f07f3d0d0b405b20c9e4199.png rename to Java/05Java文件IO与网络编程/media/0ed020222f07f3d0d0b405b20c9e4199.png diff --git a/Java/05JavaIO与网络编程/media/12ae308e42698e5ea0ffac38c42a3484.png b/Java/05Java文件IO与网络编程/media/12ae308e42698e5ea0ffac38c42a3484.png similarity index 100% rename from Java/05JavaIO与网络编程/media/12ae308e42698e5ea0ffac38c42a3484.png rename to Java/05Java文件IO与网络编程/media/12ae308e42698e5ea0ffac38c42a3484.png diff --git a/Java/05JavaIO与网络编程/media/135097b6a32d7be79d3a02754eb5017a.png b/Java/05Java文件IO与网络编程/media/135097b6a32d7be79d3a02754eb5017a.png similarity index 100% rename from Java/05JavaIO与网络编程/media/135097b6a32d7be79d3a02754eb5017a.png rename to Java/05Java文件IO与网络编程/media/135097b6a32d7be79d3a02754eb5017a.png diff --git a/Java/05JavaIO与网络编程/media/13ba18c5d137570035bb5ad25946599b.png b/Java/05Java文件IO与网络编程/media/13ba18c5d137570035bb5ad25946599b.png similarity index 100% rename from Java/05JavaIO与网络编程/media/13ba18c5d137570035bb5ad25946599b.png rename to Java/05Java文件IO与网络编程/media/13ba18c5d137570035bb5ad25946599b.png diff --git a/Java/05JavaIO与网络编程/media/1e605723a237772c2404d1bf6d5248c3.gif b/Java/05Java文件IO与网络编程/media/1e605723a237772c2404d1bf6d5248c3.gif similarity index 100% rename from Java/05JavaIO与网络编程/media/1e605723a237772c2404d1bf6d5248c3.gif rename to Java/05Java文件IO与网络编程/media/1e605723a237772c2404d1bf6d5248c3.gif diff --git a/Java/05JavaIO与网络编程/media/207fbeca9fd31ed3ab75a2b0b9803b4c.png b/Java/05Java文件IO与网络编程/media/207fbeca9fd31ed3ab75a2b0b9803b4c.png similarity index 100% rename from Java/05JavaIO与网络编程/media/207fbeca9fd31ed3ab75a2b0b9803b4c.png rename to Java/05Java文件IO与网络编程/media/207fbeca9fd31ed3ab75a2b0b9803b4c.png diff --git a/Java/05JavaIO与网络编程/media/21202143ea74374015361d25b0455b5f.png b/Java/05Java文件IO与网络编程/media/21202143ea74374015361d25b0455b5f.png similarity index 100% rename from Java/05JavaIO与网络编程/media/21202143ea74374015361d25b0455b5f.png rename to Java/05Java文件IO与网络编程/media/21202143ea74374015361d25b0455b5f.png diff --git a/Java/05JavaIO与网络编程/media/23275a1f62680918e7891389fa9a149f.png b/Java/05Java文件IO与网络编程/media/23275a1f62680918e7891389fa9a149f.png similarity index 100% rename from Java/05JavaIO与网络编程/media/23275a1f62680918e7891389fa9a149f.png rename to Java/05Java文件IO与网络编程/media/23275a1f62680918e7891389fa9a149f.png diff --git a/Java/05JavaIO与网络编程/media/23aa409dbf14d3a002a46df7d8ea5c77.png b/Java/05Java文件IO与网络编程/media/23aa409dbf14d3a002a46df7d8ea5c77.png similarity index 100% rename from Java/05JavaIO与网络编程/media/23aa409dbf14d3a002a46df7d8ea5c77.png rename to Java/05Java文件IO与网络编程/media/23aa409dbf14d3a002a46df7d8ea5c77.png diff --git a/Java/05JavaIO与网络编程/media/26005b0c83224fe160d6cb7658367c2c.png b/Java/05Java文件IO与网络编程/media/26005b0c83224fe160d6cb7658367c2c.png similarity index 100% rename from Java/05JavaIO与网络编程/media/26005b0c83224fe160d6cb7658367c2c.png rename to Java/05Java文件IO与网络编程/media/26005b0c83224fe160d6cb7658367c2c.png diff --git a/Java/05JavaIO与网络编程/media/2602720f7f65ca5d4a9d8af2abcf3569.png b/Java/05Java文件IO与网络编程/media/2602720f7f65ca5d4a9d8af2abcf3569.png similarity index 100% rename from Java/05JavaIO与网络编程/media/2602720f7f65ca5d4a9d8af2abcf3569.png rename to Java/05Java文件IO与网络编程/media/2602720f7f65ca5d4a9d8af2abcf3569.png diff --git a/Java/05JavaIO与网络编程/media/288b81f4a8937847c3e775b86b07eaa3.png b/Java/05Java文件IO与网络编程/media/288b81f4a8937847c3e775b86b07eaa3.png similarity index 100% rename from Java/05JavaIO与网络编程/media/288b81f4a8937847c3e775b86b07eaa3.png rename to Java/05Java文件IO与网络编程/media/288b81f4a8937847c3e775b86b07eaa3.png diff --git a/Java/05JavaIO与网络编程/media/29a9dcc45fcd9a687b53ae6ff8d0e7c2.png b/Java/05Java文件IO与网络编程/media/29a9dcc45fcd9a687b53ae6ff8d0e7c2.png similarity index 100% rename from Java/05JavaIO与网络编程/media/29a9dcc45fcd9a687b53ae6ff8d0e7c2.png rename to Java/05Java文件IO与网络编程/media/29a9dcc45fcd9a687b53ae6ff8d0e7c2.png diff --git a/Java/05JavaIO与网络编程/media/2ba3630488f0f2874f32bc5bd8a236dd.png b/Java/05Java文件IO与网络编程/media/2ba3630488f0f2874f32bc5bd8a236dd.png similarity index 100% rename from Java/05JavaIO与网络编程/media/2ba3630488f0f2874f32bc5bd8a236dd.png rename to Java/05Java文件IO与网络编程/media/2ba3630488f0f2874f32bc5bd8a236dd.png diff --git a/Java/05JavaIO与网络编程/media/310c3e09c44d270fe52c0e360aab83b5.png b/Java/05Java文件IO与网络编程/media/310c3e09c44d270fe52c0e360aab83b5.png similarity index 100% rename from Java/05JavaIO与网络编程/media/310c3e09c44d270fe52c0e360aab83b5.png rename to Java/05Java文件IO与网络编程/media/310c3e09c44d270fe52c0e360aab83b5.png diff --git a/Java/05JavaIO与网络编程/media/32695a79080b5d070d180cd90dc6a60f.png b/Java/05Java文件IO与网络编程/media/32695a79080b5d070d180cd90dc6a60f.png similarity index 100% rename from Java/05JavaIO与网络编程/media/32695a79080b5d070d180cd90dc6a60f.png rename to Java/05Java文件IO与网络编程/media/32695a79080b5d070d180cd90dc6a60f.png diff --git a/Java/05JavaIO与网络编程/media/339890a404ce80ccaad34f1f9f8761ab.png b/Java/05Java文件IO与网络编程/media/339890a404ce80ccaad34f1f9f8761ab.png similarity index 100% rename from Java/05JavaIO与网络编程/media/339890a404ce80ccaad34f1f9f8761ab.png rename to Java/05Java文件IO与网络编程/media/339890a404ce80ccaad34f1f9f8761ab.png diff --git a/Java/05JavaIO与网络编程/media/352644fe8e44bed2bcc5029e19f36a2d.png b/Java/05Java文件IO与网络编程/media/352644fe8e44bed2bcc5029e19f36a2d.png similarity index 100% rename from Java/05JavaIO与网络编程/media/352644fe8e44bed2bcc5029e19f36a2d.png rename to Java/05Java文件IO与网络编程/media/352644fe8e44bed2bcc5029e19f36a2d.png diff --git a/Java/05JavaIO与网络编程/media/3be95dd9e28fc013f1872e48c76e7e72.png b/Java/05Java文件IO与网络编程/media/3be95dd9e28fc013f1872e48c76e7e72.png similarity index 100% rename from Java/05JavaIO与网络编程/media/3be95dd9e28fc013f1872e48c76e7e72.png rename to Java/05Java文件IO与网络编程/media/3be95dd9e28fc013f1872e48c76e7e72.png diff --git a/Java/05JavaIO与网络编程/media/3c2c1fd4f17e7976e8a31c089251f780.png b/Java/05Java文件IO与网络编程/media/3c2c1fd4f17e7976e8a31c089251f780.png similarity index 100% rename from Java/05JavaIO与网络编程/media/3c2c1fd4f17e7976e8a31c089251f780.png rename to Java/05Java文件IO与网络编程/media/3c2c1fd4f17e7976e8a31c089251f780.png diff --git a/Java/05JavaIO与网络编程/media/3d25120fdc157d7eb22f3a1cf36a7885.png b/Java/05Java文件IO与网络编程/media/3d25120fdc157d7eb22f3a1cf36a7885.png similarity index 100% rename from Java/05JavaIO与网络编程/media/3d25120fdc157d7eb22f3a1cf36a7885.png rename to Java/05Java文件IO与网络编程/media/3d25120fdc157d7eb22f3a1cf36a7885.png diff --git a/Java/05JavaIO与网络编程/media/410d4cf19c8273fcf391b4bbcfa7b391.png b/Java/05Java文件IO与网络编程/media/410d4cf19c8273fcf391b4bbcfa7b391.png similarity index 100% rename from Java/05JavaIO与网络编程/media/410d4cf19c8273fcf391b4bbcfa7b391.png rename to Java/05Java文件IO与网络编程/media/410d4cf19c8273fcf391b4bbcfa7b391.png diff --git a/Java/05JavaIO与网络编程/media/41fd9830599e374b63260ae7dece858e.png b/Java/05Java文件IO与网络编程/media/41fd9830599e374b63260ae7dece858e.png similarity index 100% rename from Java/05JavaIO与网络编程/media/41fd9830599e374b63260ae7dece858e.png rename to Java/05Java文件IO与网络编程/media/41fd9830599e374b63260ae7dece858e.png diff --git a/Java/05JavaIO与网络编程/media/421fd9e102576846483b67c53d23f170.png b/Java/05Java文件IO与网络编程/media/421fd9e102576846483b67c53d23f170.png similarity index 100% rename from Java/05JavaIO与网络编程/media/421fd9e102576846483b67c53d23f170.png rename to Java/05Java文件IO与网络编程/media/421fd9e102576846483b67c53d23f170.png diff --git a/Java/05JavaIO与网络编程/media/46764bdc5a287633a25d30b52cf0ae1e.png b/Java/05Java文件IO与网络编程/media/46764bdc5a287633a25d30b52cf0ae1e.png similarity index 100% rename from Java/05JavaIO与网络编程/media/46764bdc5a287633a25d30b52cf0ae1e.png rename to Java/05Java文件IO与网络编程/media/46764bdc5a287633a25d30b52cf0ae1e.png diff --git a/Java/05JavaIO与网络编程/media/46851e91409fb2dce25933f725a3e1ce.png b/Java/05Java文件IO与网络编程/media/46851e91409fb2dce25933f725a3e1ce.png similarity index 100% rename from Java/05JavaIO与网络编程/media/46851e91409fb2dce25933f725a3e1ce.png rename to Java/05Java文件IO与网络编程/media/46851e91409fb2dce25933f725a3e1ce.png diff --git a/Java/05JavaIO与网络编程/media/4f027230571687bae1d7d5fd6c887262.png b/Java/05Java文件IO与网络编程/media/4f027230571687bae1d7d5fd6c887262.png similarity index 100% rename from Java/05JavaIO与网络编程/media/4f027230571687bae1d7d5fd6c887262.png rename to Java/05Java文件IO与网络编程/media/4f027230571687bae1d7d5fd6c887262.png diff --git a/Java/05JavaIO与网络编程/media/51e409b11aa51c150090697429a953ed.gif b/Java/05Java文件IO与网络编程/media/51e409b11aa51c150090697429a953ed.gif similarity index 100% rename from Java/05JavaIO与网络编程/media/51e409b11aa51c150090697429a953ed.gif rename to Java/05Java文件IO与网络编程/media/51e409b11aa51c150090697429a953ed.gif diff --git a/Java/05JavaIO与网络编程/media/53c99757ef646fb19c968c270261f997.png b/Java/05Java文件IO与网络编程/media/53c99757ef646fb19c968c270261f997.png similarity index 100% rename from Java/05JavaIO与网络编程/media/53c99757ef646fb19c968c270261f997.png rename to Java/05Java文件IO与网络编程/media/53c99757ef646fb19c968c270261f997.png diff --git a/Java/05JavaIO与网络编程/media/554c75f84f8e53347e13bc5bfae5c2ed.png b/Java/05Java文件IO与网络编程/media/554c75f84f8e53347e13bc5bfae5c2ed.png similarity index 100% rename from Java/05JavaIO与网络编程/media/554c75f84f8e53347e13bc5bfae5c2ed.png rename to Java/05Java文件IO与网络编程/media/554c75f84f8e53347e13bc5bfae5c2ed.png diff --git a/Java/05JavaIO与网络编程/media/5662bedb45e733ee84d631c05aa45a1b.png b/Java/05Java文件IO与网络编程/media/5662bedb45e733ee84d631c05aa45a1b.png similarity index 100% rename from Java/05JavaIO与网络编程/media/5662bedb45e733ee84d631c05aa45a1b.png rename to Java/05Java文件IO与网络编程/media/5662bedb45e733ee84d631c05aa45a1b.png diff --git a/Java/05JavaIO与网络编程/media/5920ee3aa726049e1d5a905a51614daa.png b/Java/05Java文件IO与网络编程/media/5920ee3aa726049e1d5a905a51614daa.png similarity index 100% rename from Java/05JavaIO与网络编程/media/5920ee3aa726049e1d5a905a51614daa.png rename to Java/05Java文件IO与网络编程/media/5920ee3aa726049e1d5a905a51614daa.png diff --git a/Java/05JavaIO与网络编程/media/5a5e5697905e0cbc15ff7a0e76a0dbfc.png b/Java/05Java文件IO与网络编程/media/5a5e5697905e0cbc15ff7a0e76a0dbfc.png similarity index 100% rename from Java/05JavaIO与网络编程/media/5a5e5697905e0cbc15ff7a0e76a0dbfc.png rename to Java/05Java文件IO与网络编程/media/5a5e5697905e0cbc15ff7a0e76a0dbfc.png diff --git a/Java/05JavaIO与网络编程/media/5c81759ac65a3e108718d187ceb1e24b.png b/Java/05Java文件IO与网络编程/media/5c81759ac65a3e108718d187ceb1e24b.png similarity index 100% rename from Java/05JavaIO与网络编程/media/5c81759ac65a3e108718d187ceb1e24b.png rename to Java/05Java文件IO与网络编程/media/5c81759ac65a3e108718d187ceb1e24b.png diff --git a/Java/05JavaIO与网络编程/media/5cf5dde716475024008c7505ed210def.png b/Java/05Java文件IO与网络编程/media/5cf5dde716475024008c7505ed210def.png similarity index 100% rename from Java/05JavaIO与网络编程/media/5cf5dde716475024008c7505ed210def.png rename to Java/05Java文件IO与网络编程/media/5cf5dde716475024008c7505ed210def.png diff --git a/Java/05JavaIO与网络编程/media/5dbaec9196d3822fbfe811ee7dc3dbd5.png b/Java/05Java文件IO与网络编程/media/5dbaec9196d3822fbfe811ee7dc3dbd5.png similarity index 100% rename from Java/05JavaIO与网络编程/media/5dbaec9196d3822fbfe811ee7dc3dbd5.png rename to Java/05Java文件IO与网络编程/media/5dbaec9196d3822fbfe811ee7dc3dbd5.png diff --git a/Java/05JavaIO与网络编程/media/5e148d9d5712418811886d86b891e823.png b/Java/05Java文件IO与网络编程/media/5e148d9d5712418811886d86b891e823.png similarity index 100% rename from Java/05JavaIO与网络编程/media/5e148d9d5712418811886d86b891e823.png rename to Java/05Java文件IO与网络编程/media/5e148d9d5712418811886d86b891e823.png diff --git a/Java/05JavaIO与网络编程/media/5f4ea984a41d2eb6cd5e2bdb760a0ad9.png b/Java/05Java文件IO与网络编程/media/5f4ea984a41d2eb6cd5e2bdb760a0ad9.png similarity index 100% rename from Java/05JavaIO与网络编程/media/5f4ea984a41d2eb6cd5e2bdb760a0ad9.png rename to Java/05Java文件IO与网络编程/media/5f4ea984a41d2eb6cd5e2bdb760a0ad9.png diff --git a/Java/05JavaIO与网络编程/media/64c795a7d1f06eb3d76e02ae2a301db9.png b/Java/05Java文件IO与网络编程/media/64c795a7d1f06eb3d76e02ae2a301db9.png similarity index 100% rename from Java/05JavaIO与网络编程/media/64c795a7d1f06eb3d76e02ae2a301db9.png rename to Java/05Java文件IO与网络编程/media/64c795a7d1f06eb3d76e02ae2a301db9.png diff --git a/Java/05JavaIO与网络编程/media/661d914f0508cf83bd6b3344bf5d1ad1.png b/Java/05Java文件IO与网络编程/media/661d914f0508cf83bd6b3344bf5d1ad1.png similarity index 100% rename from Java/05JavaIO与网络编程/media/661d914f0508cf83bd6b3344bf5d1ad1.png rename to Java/05Java文件IO与网络编程/media/661d914f0508cf83bd6b3344bf5d1ad1.png diff --git a/Java/05JavaIO与网络编程/media/682155b3d9bb95cf9e0764d21aa398df.png b/Java/05Java文件IO与网络编程/media/682155b3d9bb95cf9e0764d21aa398df.png similarity index 100% rename from Java/05JavaIO与网络编程/media/682155b3d9bb95cf9e0764d21aa398df.png rename to Java/05Java文件IO与网络编程/media/682155b3d9bb95cf9e0764d21aa398df.png diff --git a/Java/05JavaIO与网络编程/media/72d35439798aa9e9411cc9f85e65412d.png b/Java/05Java文件IO与网络编程/media/72d35439798aa9e9411cc9f85e65412d.png similarity index 100% rename from Java/05JavaIO与网络编程/media/72d35439798aa9e9411cc9f85e65412d.png rename to Java/05Java文件IO与网络编程/media/72d35439798aa9e9411cc9f85e65412d.png diff --git a/Java/05JavaIO与网络编程/media/7343332168b1cd6d2398995412c4739b.png b/Java/05Java文件IO与网络编程/media/7343332168b1cd6d2398995412c4739b.png similarity index 100% rename from Java/05JavaIO与网络编程/media/7343332168b1cd6d2398995412c4739b.png rename to Java/05Java文件IO与网络编程/media/7343332168b1cd6d2398995412c4739b.png diff --git a/Java/05JavaIO与网络编程/media/74d89c3525a5fb85f03cbb3fdea9ac0b.png b/Java/05Java文件IO与网络编程/media/74d89c3525a5fb85f03cbb3fdea9ac0b.png similarity index 100% rename from Java/05JavaIO与网络编程/media/74d89c3525a5fb85f03cbb3fdea9ac0b.png rename to Java/05Java文件IO与网络编程/media/74d89c3525a5fb85f03cbb3fdea9ac0b.png diff --git a/Java/05JavaIO与网络编程/media/7f69ee69093961598550e28f7e25719a.png b/Java/05Java文件IO与网络编程/media/7f69ee69093961598550e28f7e25719a.png similarity index 100% rename from Java/05JavaIO与网络编程/media/7f69ee69093961598550e28f7e25719a.png rename to Java/05Java文件IO与网络编程/media/7f69ee69093961598550e28f7e25719a.png diff --git a/Java/05JavaIO与网络编程/media/8b63587275597554721b193b36793bdd.png b/Java/05Java文件IO与网络编程/media/8b63587275597554721b193b36793bdd.png similarity index 100% rename from Java/05JavaIO与网络编程/media/8b63587275597554721b193b36793bdd.png rename to Java/05Java文件IO与网络编程/media/8b63587275597554721b193b36793bdd.png diff --git a/Java/05JavaIO与网络编程/media/946ac67c66320b025c977140449f2726.png b/Java/05Java文件IO与网络编程/media/946ac67c66320b025c977140449f2726.png similarity index 100% rename from Java/05JavaIO与网络编程/media/946ac67c66320b025c977140449f2726.png rename to Java/05Java文件IO与网络编程/media/946ac67c66320b025c977140449f2726.png diff --git a/Java/05JavaIO与网络编程/media/999fffbe3d46bc883b98ea7b5769a7da.png b/Java/05Java文件IO与网络编程/media/999fffbe3d46bc883b98ea7b5769a7da.png similarity index 100% rename from Java/05JavaIO与网络编程/media/999fffbe3d46bc883b98ea7b5769a7da.png rename to Java/05Java文件IO与网络编程/media/999fffbe3d46bc883b98ea7b5769a7da.png diff --git a/Java/05JavaIO与网络编程/media/a332ee101f4e360193d878fcf2bdb926.png b/Java/05Java文件IO与网络编程/media/a332ee101f4e360193d878fcf2bdb926.png similarity index 100% rename from Java/05JavaIO与网络编程/media/a332ee101f4e360193d878fcf2bdb926.png rename to Java/05Java文件IO与网络编程/media/a332ee101f4e360193d878fcf2bdb926.png diff --git a/Java/05JavaIO与网络编程/media/a984c00d0f7846158558aa25291e6a83.png b/Java/05Java文件IO与网络编程/media/a984c00d0f7846158558aa25291e6a83.png similarity index 100% rename from Java/05JavaIO与网络编程/media/a984c00d0f7846158558aa25291e6a83.png rename to Java/05Java文件IO与网络编程/media/a984c00d0f7846158558aa25291e6a83.png diff --git a/Java/05JavaIO与网络编程/media/ab38369f8043d690b448fe8e8004a755.png b/Java/05Java文件IO与网络编程/media/ab38369f8043d690b448fe8e8004a755.png similarity index 100% rename from Java/05JavaIO与网络编程/media/ab38369f8043d690b448fe8e8004a755.png rename to Java/05Java文件IO与网络编程/media/ab38369f8043d690b448fe8e8004a755.png diff --git a/Java/05JavaIO与网络编程/media/ac2af137ab9c52245d2e72ceafffee76.png b/Java/05Java文件IO与网络编程/media/ac2af137ab9c52245d2e72ceafffee76.png similarity index 100% rename from Java/05JavaIO与网络编程/media/ac2af137ab9c52245d2e72ceafffee76.png rename to Java/05Java文件IO与网络编程/media/ac2af137ab9c52245d2e72ceafffee76.png diff --git a/Java/05JavaIO与网络编程/media/b24ac0390788e8547c3f60daee9eaacf.jpeg b/Java/05Java文件IO与网络编程/media/b24ac0390788e8547c3f60daee9eaacf.jpeg similarity index 100% rename from Java/05JavaIO与网络编程/media/b24ac0390788e8547c3f60daee9eaacf.jpeg rename to Java/05Java文件IO与网络编程/media/b24ac0390788e8547c3f60daee9eaacf.jpeg diff --git a/Java/05JavaIO与网络编程/media/b2c4e7c54fc6c246e437b80f8752b75d.png b/Java/05Java文件IO与网络编程/media/b2c4e7c54fc6c246e437b80f8752b75d.png similarity index 100% rename from Java/05JavaIO与网络编程/media/b2c4e7c54fc6c246e437b80f8752b75d.png rename to Java/05Java文件IO与网络编程/media/b2c4e7c54fc6c246e437b80f8752b75d.png diff --git a/Java/05JavaIO与网络编程/media/b8e04854836dbd4d12d08351c1e70332.png b/Java/05Java文件IO与网络编程/media/b8e04854836dbd4d12d08351c1e70332.png similarity index 100% rename from Java/05JavaIO与网络编程/media/b8e04854836dbd4d12d08351c1e70332.png rename to Java/05Java文件IO与网络编程/media/b8e04854836dbd4d12d08351c1e70332.png diff --git a/Java/05JavaIO与网络编程/media/b9541e310983abc3936b385e852c23b0.png b/Java/05Java文件IO与网络编程/media/b9541e310983abc3936b385e852c23b0.png similarity index 100% rename from Java/05JavaIO与网络编程/media/b9541e310983abc3936b385e852c23b0.png rename to Java/05Java文件IO与网络编程/media/b9541e310983abc3936b385e852c23b0.png diff --git a/Java/05JavaIO与网络编程/media/bf6e89db6228034cd1d1f820a54d9332.png b/Java/05Java文件IO与网络编程/media/bf6e89db6228034cd1d1f820a54d9332.png similarity index 100% rename from Java/05JavaIO与网络编程/media/bf6e89db6228034cd1d1f820a54d9332.png rename to Java/05Java文件IO与网络编程/media/bf6e89db6228034cd1d1f820a54d9332.png diff --git a/Java/05JavaIO与网络编程/media/c0987f0a7d6c303402b2dceb1d8d6f13.png b/Java/05Java文件IO与网络编程/media/c0987f0a7d6c303402b2dceb1d8d6f13.png similarity index 100% rename from Java/05JavaIO与网络编程/media/c0987f0a7d6c303402b2dceb1d8d6f13.png rename to Java/05Java文件IO与网络编程/media/c0987f0a7d6c303402b2dceb1d8d6f13.png diff --git a/Java/05JavaIO与网络编程/media/dca5742acd83b6d3f86f5b3af9cf1fcb.png b/Java/05Java文件IO与网络编程/media/dca5742acd83b6d3f86f5b3af9cf1fcb.png similarity index 100% rename from Java/05JavaIO与网络编程/media/dca5742acd83b6d3f86f5b3af9cf1fcb.png rename to Java/05Java文件IO与网络编程/media/dca5742acd83b6d3f86f5b3af9cf1fcb.png diff --git a/Java/05JavaIO与网络编程/media/e9ef17fc1494294fd805ec482f8fe2cc.png b/Java/05Java文件IO与网络编程/media/e9ef17fc1494294fd805ec482f8fe2cc.png similarity index 100% rename from Java/05JavaIO与网络编程/media/e9ef17fc1494294fd805ec482f8fe2cc.png rename to Java/05Java文件IO与网络编程/media/e9ef17fc1494294fd805ec482f8fe2cc.png diff --git a/Java/05JavaIO与网络编程/media/eaac8b5cec8dde91bba8c2d0ebf4df12.png b/Java/05Java文件IO与网络编程/media/eaac8b5cec8dde91bba8c2d0ebf4df12.png similarity index 100% rename from Java/05JavaIO与网络编程/media/eaac8b5cec8dde91bba8c2d0ebf4df12.png rename to Java/05Java文件IO与网络编程/media/eaac8b5cec8dde91bba8c2d0ebf4df12.png diff --git a/Java/05JavaIO与网络编程/media/f28b2b1dc1614e898cb4255e41d37d00.png b/Java/05Java文件IO与网络编程/media/f28b2b1dc1614e898cb4255e41d37d00.png similarity index 100% rename from Java/05JavaIO与网络编程/media/f28b2b1dc1614e898cb4255e41d37d00.png rename to Java/05Java文件IO与网络编程/media/f28b2b1dc1614e898cb4255e41d37d00.png diff --git a/Java/05JavaIO与网络编程/media/f2f880588756d88cbf5083a94fbd41ae.jpeg b/Java/05Java文件IO与网络编程/media/f2f880588756d88cbf5083a94fbd41ae.jpeg similarity index 100% rename from Java/05JavaIO与网络编程/media/f2f880588756d88cbf5083a94fbd41ae.jpeg rename to Java/05Java文件IO与网络编程/media/f2f880588756d88cbf5083a94fbd41ae.jpeg diff --git a/Java/05JavaIO与网络编程/media/f4495b0ffb8c7fa60db31e6bfad35328.png b/Java/05Java文件IO与网络编程/media/f4495b0ffb8c7fa60db31e6bfad35328.png similarity index 100% rename from Java/05JavaIO与网络编程/media/f4495b0ffb8c7fa60db31e6bfad35328.png rename to Java/05Java文件IO与网络编程/media/f4495b0ffb8c7fa60db31e6bfad35328.png diff --git a/Java/05JavaIO与网络编程/media/f5953ff98bf276f97b08461d9460e10b.png b/Java/05Java文件IO与网络编程/media/f5953ff98bf276f97b08461d9460e10b.png similarity index 100% rename from Java/05JavaIO与网络编程/media/f5953ff98bf276f97b08461d9460e10b.png rename to Java/05Java文件IO与网络编程/media/f5953ff98bf276f97b08461d9460e10b.png diff --git a/Java/05JavaIO与网络编程/media/f658002b86035d44ed08b7e2dbd4fffc.png b/Java/05Java文件IO与网络编程/media/f658002b86035d44ed08b7e2dbd4fffc.png similarity index 100% rename from Java/05JavaIO与网络编程/media/f658002b86035d44ed08b7e2dbd4fffc.png rename to Java/05Java文件IO与网络编程/media/f658002b86035d44ed08b7e2dbd4fffc.png diff --git a/Java/05JavaIO与网络编程/media/f837ce408bd2404325047c0762c206db.png b/Java/05Java文件IO与网络编程/media/f837ce408bd2404325047c0762c206db.png similarity index 100% rename from Java/05JavaIO与网络编程/media/f837ce408bd2404325047c0762c206db.png rename to Java/05Java文件IO与网络编程/media/f837ce408bd2404325047c0762c206db.png diff --git a/Java/05JavaIO与网络编程/media/f8f1212105e495ccfca7866fb6baaf26.png b/Java/05Java文件IO与网络编程/media/f8f1212105e495ccfca7866fb6baaf26.png similarity index 100% rename from Java/05JavaIO与网络编程/media/f8f1212105e495ccfca7866fb6baaf26.png rename to Java/05Java文件IO与网络编程/media/f8f1212105e495ccfca7866fb6baaf26.png diff --git a/Java/05JavaIO与网络编程/media/f9577fd8236c564d81c08514aaa46e3c.png b/Java/05Java文件IO与网络编程/media/f9577fd8236c564d81c08514aaa46e3c.png similarity index 100% rename from Java/05JavaIO与网络编程/media/f9577fd8236c564d81c08514aaa46e3c.png rename to Java/05Java文件IO与网络编程/media/f9577fd8236c564d81c08514aaa46e3c.png diff --git a/Java/05JavaIO与网络编程/media/fb087dd562da5b0cebc1224cb5c0e3ac.png b/Java/05Java文件IO与网络编程/media/fb087dd562da5b0cebc1224cb5c0e3ac.png similarity index 100% rename from Java/05JavaIO与网络编程/media/fb087dd562da5b0cebc1224cb5c0e3ac.png rename to Java/05Java文件IO与网络编程/media/fb087dd562da5b0cebc1224cb5c0e3ac.png diff --git a/Java/05JavaIO与网络编程/media/fde4f0671aec53278e9e0cdf7c6f9b6d.png b/Java/05Java文件IO与网络编程/media/fde4f0671aec53278e9e0cdf7c6f9b6d.png similarity index 100% rename from Java/05JavaIO与网络编程/media/fde4f0671aec53278e9e0cdf7c6f9b6d.png rename to Java/05Java文件IO与网络编程/media/fde4f0671aec53278e9e0cdf7c6f9b6d.png diff --git a/Java/05JavaIO与网络编程/media/fdff5669c899369c5ac4faa37e6a2df3.png b/Java/05Java文件IO与网络编程/media/fdff5669c899369c5ac4faa37e6a2df3.png similarity index 100% rename from Java/05JavaIO与网络编程/media/fdff5669c899369c5ac4faa37e6a2df3.png rename to Java/05Java文件IO与网络编程/media/fdff5669c899369c5ac4faa37e6a2df3.png diff --git a/Java/05JavaIO与网络编程/附录1:分布式计算.md b/Java/05Java文件IO与网络编程/附录1:分布式计算.md similarity index 100% rename from Java/05JavaIO与网络编程/附录1:分布式计算.md rename to Java/05Java文件IO与网络编程/附录1:分布式计算.md diff --git a/Java/05JavaIO与网络编程/附录2:流的选择.md b/Java/05Java文件IO与网络编程/附录2:流的选择.md similarity index 100% rename from Java/05JavaIO与网络编程/附录2:流的选择.md rename to Java/05Java文件IO与网络编程/附录2:流的选择.md diff --git a/Java/05JavaIO与网络编程/附录3:IO、网络编程与web开发的关系.md b/Java/05Java文件IO与网络编程/附录3:IO、网络编程与web开发的关系.md similarity index 100% rename from Java/05JavaIO与网络编程/附录3:IO、网络编程与web开发的关系.md rename to Java/05Java文件IO与网络编程/附录3:IO、网络编程与web开发的关系.md diff --git a/Java/Java三方库/Junit.md b/Java/06Java生态库/Junit.md similarity index 100% rename from Java/Java三方库/Junit.md rename to Java/06Java生态库/Junit.md diff --git a/Java/Java三方库/Lombok.md b/Java/06Java生态库/Lombok.md similarity index 100% rename from Java/Java三方库/Lombok.md rename to Java/06Java生态库/Lombok.md diff --git a/Java/Java三方库/apa b/Java/06Java生态库/apa similarity index 100% rename from Java/Java三方库/apa rename to Java/06Java生态库/apa diff --git a/Java/Java三方库/apache-httpcomponents.md b/Java/06Java生态库/apache-httpcomponents.md similarity index 100% rename from Java/Java三方库/apache-httpcomponents.md rename to Java/06Java生态库/apache-httpcomponents.md diff --git a/Java/Java三方库/caffeine.md b/Java/06Java生态库/caffeine.md similarity index 100% rename from Java/Java三方库/caffeine.md rename to Java/06Java生态库/caffeine.md diff --git a/Java/Java三方库/commons-bean.md b/Java/06Java生态库/commons-bean.md similarity index 100% rename from Java/Java三方库/commons-bean.md rename to Java/06Java生态库/commons-bean.md diff --git a/Java/Java三方库/commons-collections4.md b/Java/06Java生态库/commons-collections4.md similarity index 100% rename from Java/Java三方库/commons-collections4.md rename to Java/06Java生态库/commons-collections4.md diff --git a/Java/Java三方库/commons-io.md b/Java/06Java生态库/commons-io.md similarity index 100% rename from Java/Java三方库/commons-io.md rename to Java/06Java生态库/commons-io.md diff --git a/Java/Java三方库/commons-lang3.md b/Java/06Java生态库/commons-lang3.md similarity index 100% rename from Java/Java三方库/commons-lang3.md rename to Java/06Java生态库/commons-lang3.md diff --git a/Java/Java三方库/commons-logging.md b/Java/06Java生态库/commons-logging.md similarity index 100% rename from Java/Java三方库/commons-logging.md rename to Java/06Java生态库/commons-logging.md diff --git a/Java/Java三方库/fastjson.md b/Java/06Java生态库/fastjson.md similarity index 100% rename from Java/Java三方库/fastjson.md rename to Java/06Java生态库/fastjson.md diff --git a/Java/Java三方库/gson.md b/Java/06Java生态库/gson.md similarity index 100% rename from Java/Java三方库/gson.md rename to Java/06Java生态库/gson.md diff --git a/Java/Java三方库/image/2022-11-15-14-38-18.png b/Java/06Java生态库/image/2022-11-15-14-38-18.png similarity index 100% rename from Java/Java三方库/image/2022-11-15-14-38-18.png rename to Java/06Java生态库/image/2022-11-15-14-38-18.png diff --git a/Java/Java三方库/log4j.md b/Java/06Java生态库/log4j.md similarity index 100% rename from Java/Java三方库/log4j.md rename to Java/06Java生态库/log4j.md diff --git a/Java/Java三方库/logback.md b/Java/06Java生态库/logback.md similarity index 100% rename from Java/Java三方库/logback.md rename to Java/06Java生态库/logback.md diff --git a/Java/Java三方库/micrometer.md b/Java/06Java生态库/micrometer.md similarity index 100% rename from Java/Java三方库/micrometer.md rename to Java/06Java生态库/micrometer.md diff --git a/Java/Java三方库/mockito.md b/Java/06Java生态库/mockito.md similarity index 100% rename from Java/Java三方库/mockito.md rename to Java/06Java生态库/mockito.md diff --git a/Java/Java三方库/slf4j.md b/Java/06Java生态库/slf4j.md similarity index 100% rename from Java/Java三方库/slf4j.md rename to Java/06Java生态库/slf4j.md diff --git a/Java/Java三方库/sofabolt.md b/Java/06Java生态库/sofabolt.md similarity index 100% rename from Java/Java三方库/sofabolt.md rename to Java/06Java生态库/sofabolt.md diff --git a/Java/JVM原理/01 Java编译原理.md b/Java/07JVM编译原理/01 Java编译原理.md similarity index 70% rename from Java/JVM原理/01 Java编译原理.md rename to Java/07JVM编译原理/01 Java编译原理.md index 631645ca..6137f7e1 100644 --- a/Java/JVM原理/01 Java编译原理.md +++ b/Java/07JVM编译原理/01 Java编译原理.md @@ -93,3 +93,143 @@ Java HotSpot(TM) 64-Bit Server VM (build 25.291-b10, mixed mode) 如果能证明一个对象不会逃逸到方法或线程外,则可能为这个变量进行一些高效的优化, 如栈上替换、同步消除、标量替换。 +## 5 Jdk21的编译实践 + +下面给出一份经过验证的 **Ubuntu 22.04 LTS** 上 **从源码完整编译 OpenJDK(以 JDK 21 为例)** 的实战流程。 + +--- + +### 1️⃣ 一次装好全部系统依赖 + +```bash +sudo apt update && sudo apt upgrade -y +sudo apt install -y build-essential autoconf zip unzip \ + libx11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev \ + libcups2-dev libfontconfig1-dev libasound2-dev libffi-dev \ + libelf-dev libdwarf-dev systemtap-sdt-dev +``` + +> JDK 21 比 17 多了 `libffi-dev libelf-dev libdwarf-dev systemtap-sdt-dev` 等调试/性能分析依赖,建议一次性装上,避免中途缺包。 + +--- + +### 2️⃣ 准备 Boot JDK(JDK 20 或 21 均可) + +Ubuntu 官方仓库已有 21: + +```bash +sudo apt install openjdk-21-jdk +``` + +确认版本: + +```bash +java -version # 期望看到 openjdk 21.x +``` + +--- + +### 3️⃣ 拉取源码 + +```bash +git clone https://github.com/openjdk/jdk21u.git +cd jdk21u +git checkout jdk-21+35 # 当前 GA 版本 tag +``` + +--- + +### 4️⃣ 生成配置(configure) + + +初次编译不明白各个配置项的含义可以直接运行罗命令,不需要自己指定配置项 +```bash +bash configure \ + --with-boot-jdk=/usr/lib/jvm/java-21-openjdk-amd64 \ + --with-debug-level=release \ + --with-jvm-variants=server \ + --disable-warnings-as-errors +``` + +常见选项说明 +- `--with-debug-level=release`:发布级别,体积最小。 +- `--with-jvm-variants=server`:只编 Server VM,节省一半时间。 +- `--disable-warnings-as-errors`:避免因警告导致编译失败。 + +出现 `A new configuration has been successfully created` 字样即代表配置通过。 + +在本地机器中执行上述命令,最后会输出一个总结 +``` + +==================================================== +A new configuration has been successfully created in +/home/estom/work/jdk21u/build/linux-x86_64-server-release +using default settings. + +Configuration summary: +* Name: linux-x86_64-server-release +* Debug level: release +* HS debug level: product +* JVM variants: server +* JVM features: server: 'cds compiler1 compiler2 dtrace epsilongc g1gc jfr jni-check jvmci jvmti management parallelgc serialgc services shenandoahgc vm-structs zgc' +* OpenJDK target: OS: linux, CPU architecture: x86, address length: 64 +* Version string: 21-internal-adhoc.estom.jdk21u (21-internal) +* Source date: 1755094786 (2025-08-13T14:19:46Z) + +Tools summary: +* Boot JDK: openjdk version "21.0.8" 2025-07-15 OpenJDK Runtime Environment (build 21.0.8+9-Ubuntu-0ubuntu122.04.1) OpenJDK 64-Bit Server VM (build 21.0.8+9-Ubuntu-0ubuntu122.04.1, mixed mode, sharing) (at /usr/lib/jvm/java-21-openjdk-amd64) +* Toolchain: gcc (GNU Compiler Collection) +* C Compiler: Version 11.4.0 (at /usr/bin/gcc) +* C++ Compiler: Version 11.4.0 (at /usr/bin/g++) + +Build performance summary: +* Build jobs: 8 +* Memory limit: 31721 MB +``` + +可以使用以下命令查看帮助命令 +```sh +bash configure --help +``` + +--- + +### 5️⃣ 编译 & 打包镜像 + +```bash +make images JOBS=$(nproc) +``` + +- 首次完整编译 8–16 线程 + SSD 约 15–25 分钟。 +- 成功后产物在 + `build/linux-x86_64-server-release/images/jdk` + +编译后的文件说明 +![编译后的目录结构](image/2025-08-13T14:44:27.336Z.png) +--- + +### 6️⃣ 验证 + +```bash +./build/linux-x86_64-server-release/images/jdk/bin/java -version +``` + +期望输出: + +``` +openjdk version "21.0.5-internal" 2024-10-15 +OpenJDK Runtime Environment (build 21.0.5-internal-xxx) +OpenJDK 64-Bit Server VM (build 21.0.5-internal-xxx, mixed mode) +``` + +--- + +### 7️⃣ 可选:安装到系统 + +```bash +sudo mkdir -p /opt/java +sudo cp -r build/linux-x86_64-server-release/images/jdk /opt/java/jdk-21-self +echo 'export JAVA_HOME=/opt/java/jdk-21-self' | sudo tee /etc/profile.d/jdk21.sh +echo 'export PATH=$JAVA_HOME/bin:$PATH' | sudo tee -a /etc/profile.d/jdk21.sh +source /etc/profile +``` diff --git a/Java/07JVM编译原理/02 Java内存区域与内存溢出.md b/Java/07JVM编译原理/02 Java内存区域与内存溢出.md new file mode 100644 index 00000000..f832a3a9 --- /dev/null +++ b/Java/07JVM编译原理/02 Java内存区域与内存溢出.md @@ -0,0 +1,62 @@ +# 2 Java内存区域与内存溢出异常 + +## 2.1 概述 + +虚拟机提供的最大的能力:自动内存管理。不再需要用户为每一个操作去写配对的delete、free代码,不需要手动管理内存的申请和释放,不容易出现内存泄漏的问题。这也符合并奠定了Java的操作哲学,**通过各种各样的运行时接管一些常规的传统语言的操作**。 + + +## 2.2 运行时内存区域 + + +![内存区域](image/2025-08-17T11:54:09.045Z.png) + +1. 程序计数器:当前线程所执行的字节码的行号指示器。多线程通过线程切换、分配处理器执行,每条线程都需要一个独立的程序计数器,各线程之间计数器互不影响、独立存储,是线程私有的内存。 +2. Java虚拟机栈:Java方法执行的内存模型。每个方法执行的时候,创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。线程私有的内存。局部变量表存放了编译器可知的各种Java虚拟机基本变量类型、对象引用、返回地址类型,局部变量表所需要的空间是在编译期间分配完成的,运行过程中,当进入一个方法时,这个方法需要再栈帧中分配多大的局部变量空间是完全确定的。 +3. 本地方法栈:本地方法的栈帧。也是线程私有的内存。 +4. 堆:用于存放对象实例。被所有线程共享的一块内存区域,是垃圾收集器管理的内存区域。可以处在物理上不连续的内存空间。通过虚拟机参数-Xmx和Xms控制堆的大小。当Java堆无法再扩展时,就会抛出OOM异常。 +5. 方法区:存储已经被虚拟机加载的类信息、常量、静态变量,即时编译后的代码缓存等数据。 +6. 运行时常量池:方法区的一部分。Class文件包括版本、字段、方法、接口等描述信息,还有常量池表,用来存放编译期产生的各种字面常量与符号引用。运行时常量池具有动态性,不仅包括编译期产生的常量与符号引用,还包括运行期将常量放入常量池中,例如通过String的intern()方法创建的字符串常量。常量池无法再申请到内存时会抛出OOM异常。 +7. 直接内存:NIO的通过和缓冲区可以使用Native函数库直接分配堆外内存,然后通过存储在Java堆里的DirectByteBuffer对象作为这块内存的引用进行操作。这样操作能够显著提高性能,避免在Java堆和Native堆中来回复制数据。本机的内存分配不会受到Java堆大小的限制。 + +![内存溢出](image/2025-08-17T13:03:25.913Z.png) +## 2.3 虚拟机对象 + +### 对象创建的过程 +![创建过程](image/2025-08-17T13:04:27.869Z.png) +1. 遇到一个new命令 +2. 检查类。检查这个指令的参数,是否能在常量池中定位到一个类的符号引用,如果没有那么必须执行类加载过程,如果检查到这个符号,则代表这个类已经被加载、解析和初始化过。 +3. 分配内存。对象所需要的内存大小在类加载完成后便可以确定。 + 1. 指针碰撞:假如是规整内存,使用过的内存和未使用的内存都会规整存放,两者中间通过分界点指示器分割,那么分配内存就是移动一下分界点的指针。空闲内存列表:如果内存并不规整,虚拟机维护了一个可用的内存列表,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新可用内存列表。 + 2. Serial和ParNew等收集器带有内存压缩能力,采用了指针碰撞方式。CMS标记清楚算法收集器采用空闲内存列表的方式分配内存。 + 3. 并发安全问题:CAS保证内存分配操作的原子性。本地线程分配缓存,每个线程在Java堆中预先分配一小块内存,内存分配动作按照线程划分在不同的空间中运行, +4. 初始化:初始化内存值,将分配到的内存初始化位0.初始化对象头,包括类指针,对象的哈希码,对象的GC分代年龄等信息。 +5. 执行用户初始化操作:执行方法,按照程序员的意愿对对象进行初始化。 + +![ ](image/2025-08-17T13:04:41.104Z.png) + +### 对象的内存布局 + +对象在堆内存中的存储布局分为三部分:对象头,实例数据,对齐填充。 +![alt text](image/2025-08-17T13:04:58.569Z.png) + +1. 对象头:哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳。还包括类型指针,指向它的类型元数据的指针,通过这个指针可以确定对象属于哪个类的实力。对于Java数组这里还会保存数组的长度。 +2. 实例数据:真正存储的有效信息,程序代码里定义的各种类型段内容。 +3. 对齐填充。8字节的整数倍。 + + +### 对象的访问定位 + +Java程序通过栈上的reference数据来操作堆上的具体对象。 +1. 句柄访问。对象移动的时候改变句柄值即可。 +![alt text](image/2025-08-17T13:08:54.326Z.png) +2. 访问速度快减少一次寻址操作。 +![alt text](image/2025-08-17T13:09:12.527Z.png) + +## 2.4 OOM + +各种触发OOM的方式 +1. OOM:Java heap Space:不断地创建新的对象 -Xms20m -Xmx20m +2. 虚拟机栈和本地方法栈:无限制递归、不断创建线程执行方法 +3. 方法区和常量池:不断执行String::intern()、使用CGlib不断创建类 -XX:MaxMetaspaceSize -XX:MaxPermSize +4. 本机直接内存溢出:Usafe不断直接分配内存空间 -XX:MaxDirectMemorySize + diff --git a/Java/07JVM编译原理/03 Java垃圾收集和内存分配.md b/Java/07JVM编译原理/03 Java垃圾收集和内存分配.md new file mode 100644 index 00000000..b8248503 --- /dev/null +++ b/Java/07JVM编译原理/03 Java垃圾收集和内存分配.md @@ -0,0 +1,368 @@ +# 3 垃圾收集器与内存分配策略 + +> https://github.com/TangBean/understanding-the-jvm/blob/master/Ch1-Java%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E6%9C%BA%E5%88%B6/02-%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86(GC).md + +## 3.1 概述 + +### 垃圾收集器的概念 + +定义:在应用程序运行时,应用程序会创建许多对象,每个对象都有其生命周期。 在内存中,被其他对象引用的对象被称为live objects 。 不再由任何活动对象引用的对象被视为dead objects ,并称为garbage 。 查找和释放(也称为回收)这些对象使用的空间的过程称为garbage collection 。 + +范围:在Java内存运行区域中,私有内存(程序计数器、虚拟机栈、本地方法栈)都是随着线程创建或者销毁。栈中的栈帧随着方法的进入和退出进行入栈和出栈操作。每一个栈帧多少内存基本上是在类结构确定下来的时候就是已经知道地,会由及时编译器进行优化。这里讨论的垃圾回收机制,主要针对堆上的内存,只有层序运行期间我们才会知道究竟会创建哪些对象、创建多少个对象,这一部分的内存分配是动态的。 + +职责:Java中的Memory management是垃圾收集器的职责。 +* allocating memory +* 确保所有引用的对象都保留在内存中,并且 +* 恢复由执行代码中的引用无法访问的对象使用的内存。 + + +垃圾回收解决了许多但不是全部的内存分配问题。 例如,我们可以无限期地创建对象并继续引用它们,直到没有更多可用内存为止( Out of memory error )。 垃圾收集是一项复杂的任务,需要花费时间和资源。 它在通常由称为堆的大型内存池分配的空间上运行。 + +垃圾收集的时间取决于垃圾收集器。 通常,整个堆或堆的一部分会在堆满或达到占用率的百分比时收集。 + +## 3.2 垃圾判定算法 + +### 引用计数算法 + +概念: 在引用计数技术中,每个对象都有从其他对象和堆栈指向该对象的指针数。 每次引用新对象时,计数器都会增加一。 同样,当任何对象丢失其引用时,计数器将减一。 当count达到'0'时,垃圾回收器可以取消分配对象。 + +引用计数算法的主要优点是:占用了少量的额外内存进行计数,但是原理十分简单,判定效率很高。 但是它存在循环引用的问题:当第一个对象被第二个对象引用,第二个对象被第一个对象( cyclic references ) cyclic references ,计数永远不会为零,因此它们永远不会被垃圾回收。 + +### 可达性分析算法 + +概念:通过一系列称为GC Roots的跟对象作为起始节点集,从节点开始根据引用关系向下搜索,搜索过程所走过的路称为引用链,如果某个对象到GC Roots没有引用,则该对象不可能再被使用。 + +常见的GC Roots对象包括 +* 在虚拟机栈中引用的对象。例如当前正在运行的方法的参数、局部变量等。 +* 在方法区中静态属性引用的对象。例如Java类中的静态变量。 +* 在静态方法区中常量引用的对象。例如字符串常量池中的引用。 +* Java虚拟机内部的引用,基本数据类型对应的Class对象 +* 所有被同步所锁持有的对象 +* 反映Java虚拟机内部的情况,JMXBean、JBMTI中注册的回调,本地代码缓存等。 +* 分区垃圾收集算法,还需要将跨区引用作为计算的一部分。 + + +### 引用类型 +对引用的类型进行扩充 +* 强引用,传统的直接引用。垃圾收集器永远不会回收掉被引用的对象。 +* 软引用,SofaReference。系统发生内存溢出前进行回收。 +* 弱引用,WeakReference。只能生存到下一次垃圾收集发生为止。 +* 虚引用,PhantomReference。虚引用的存在完全不影响垃圾收集。 + + +### 自我拯救 + +一个对象真正的死亡会经历两次标记的过程, +1. 首先对象在进行可达性分析的时候没有与GCRoots相连接,会被第一次标记。 +2. 然后给予是否执行过finalizer()方法进行第二次标记,如果执行过则标记结束,如果没执行过需要加入F-Queue队列中,并在稍后由虚拟机自动建立的、低调度优先级的Finalizer线程去执行他们的finalize()方法。 + +### 方法区的回收 + +方法去垃圾手机的性价比非常低。方法去垃圾收集主要回收两部分内容: +1. 废弃的常量 +2. 不再使用的类型 + + +## 3.3 垃圾收集算法 + +### 分代收集理论 +分代收集理论建立在两个假说的基础上: +* 弱分代假说:绝大多数对象都是朝生夕灭。 +* 强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。 +* 跨代引用假说:跨代引用相对于同代引用来说仅占极少数。因为存在引用关系的两个对象,应该倾向于同时生存或者同时消亡。 + +收集器将Java堆划分成不同的区域,然后将对象依据年龄分配到不同区域中存储。这样不用为了少量的跨代引用去扫描整个老年代,不用浪费空间专门记录每一个对象是否存在,以及存在哪些跨代引用。只需要在新生代上建立一个全局的数据结构——记忆集。这样在发生miniorGC的时候,只需要将存在跨代引用的小块内存里的对象加入到GCRoots进行扫描。 + +在java堆划分出不同区域之后,垃圾收集器可以每次只回收其中一个或者某些部分的数据。就可以针对不同区域,安排与里面存储对象存亡特征相匹配的垃圾收集算法。因而诞生了三种主要的垃圾收集算法 +* 标记复制算法 +* 标记清除算法 +* 标记整理算法 + + +根据垃圾收集的范围不同,可以将垃圾收集分为以下几种类型: +* 部分收集PratialGC + * 新生代收集MinorGC/YoungGC + * 老年代收集MajorGC/OldGC + * 混合收集MixedGC +* 整堆收集FullGC + +### 标记清除算法 + +![](image/2022-12-19-17-19-40.png) + +标记清除算法是第一个开发的able to reclaim cyclic data structures垃圾收集算法。 在这种算法中,GC将首先将某些对象标识为默认可达对象,这些对象通常是堆栈中的全局变量和局部变量。 有所谓的活动对象。在下一步中,算法开始从这些活动对象中跟踪对象,并将它们也标记为活动对象。 继续执行此过程,直到检查所有对象并将其标记为活动。 完全跟踪后未标记为活动的对象被视为死对象。 + + + +* 暂停应用程序一段时间外, +* 该技术还需要经常对内存地址空间de-fragmentation清除碎片整理 + + + +### 标记复制算法 + +像“标记和清除”一样,该算法还取决于识别活动对象并对其进行标记。 区别在于它处​​理活动对象的方式。停止和复制技术将整个堆设计为两个semi-spaces 。 一次只有一个半空间处于活动状态,而为新创建的对象分配的内存仅发生在单个半空间中,而另一个保持平静。GC运行时,它将开始标记当前半空间中的活动对象,完成后,它将所有活动对象复制到其他半空间中。 当前半空间中的所有其余对象都被视为已死,并已被垃圾回收。 + +* 接触活动对象。但是如果内存中大部分对象都是存活的,将产生大量内存复制的开销。 +* 不需要考虑空间碎片的问题,会直接进行空间的压缩。 +* 需要将所需的内存大小增加一倍,因为在给定的时间点仅使用一半的内存。 +* 需要在切换半空间时停止世界。 + +在标记清除算法上做的改进: +1. 新生代中有98%的对象熬不过第一轮,所以不需要按照1:1的比例来划分新生代中的内存空间。 +2. Appel式回收算法,将空间分为一块较大的Eden和两块较小的Survivor,每次空间分配只使用Eden和其中一块Survior。发生垃圾收集的时候,将内存中的对象都复制到空闲的Survivor上。一般情况下空间比例式8:1:1,如果出现例外情况,Survivor的空间不足,就会依赖其他内存区域进行担保。 + +### 标记整理算法 + +与标记复制算法相似,但是整理是将所有存活的对象向内存空间的一端移动,然后直接清理到边界以外的内存。 + +优缺点: +1. 存在大量存活的对象,移动对象并更新引用是一种负重的操作。 +2. 必须要暂停用户的应用进程才能进行。 + +## 3.4 HotSpot算法实现细节 + +### 根节点枚举 + +1. 根节点枚举必须暂停用户线程。 +2. 使用OopMap快速扫描GCRoots + +### 安全点 + +1. OopMap只在安全点进行记录。用户进程运行到安全点的时候才可以安全的挂起等待GCRoots的扫描。 +2. 安全点在指令复用中才会记录,如方法调用、循环跳转、异常跳转。 +3. 用户进程采用主动式中断的方式在安全点挂起。 + +### 安全区域 +上述安全点方案可以解决运行中的用户线程停顿的时机,但是处于阻塞状态的用户线程无法感知到虚拟机GC中断请求。安全区域确保在某一段代码片段中,引用关系不会发生变化。 + +这样用户进程在进入安全区域的时候,会标识自己已经进入安全区域。当离开的时候,会检测是否已经完成GCRoots的枚举。 + +### 记忆集与卡表 + +为了解决跨代对象引用的问题,避免在新生代垃圾收集的时候将整个老年代的对象加入到GCRoots当中。 + +记忆集是从非收集区域指向收集区域的指针集合的抽象数据结构。 + +如果记录全部的跨代指针会浪费时间和空间,所以直接记录某个一存在跨代指针的区域。卡表是记忆集的一种实现,就是用来记录这样的存在跨代引用的内存区域的数据结构,它定义了记忆集的记录精度、与堆内存的映射关系。 + +卡表中的每一个元素对应其标识的内存区域中一块特定大小的内存块,这个内存块被称为卡页。 + + +### 写屏障 + +卡表上记录了跨代引用,需要再对象赋值的时候维护卡表的数据。 + +通过写屏障技术维护卡表的状态。写屏障可以看做在虚拟机层面对引用类型字段赋值这个动作的AOP切面。在引用对象赋值的时候会产生一个环形通知,供程序执行额外的操作。 + + +### 并行可达性分析 + + +首先可达性分析算法要求全过程基于一个能够保证一致性的快照当中才能进行分析,必须冻结全部的用户线程。主要包括以下两个步骤 +1. 根节点枚举。这个步骤必须进行用户线程冻结。 +2. GCRoots向下遍历对象图,可以进行并行操作。 + + +引入三色标记的理论 +* 白色:对象尚未被垃圾收集器访问过。 +* 黑色:对象已经被垃圾收集器访问过,并且对象的所有引用都已经扫描过。 +* 灰色:对象已经被垃圾收集器扫描过,但是对象上至少存在一个引用还没有被扫描过。 + + +在并发扫描过程中可能会出现以下问题,可以从三色标记理论出发描述一下两种错误发生的场景: +* 原本消亡的对象被错误标记成存活。这个可以容忍,下次GC会回收掉。 +* 原本存活的对象被错误标记为消亡。这个无法容忍,会导致用户进程出错。灰色标记中的对象引用断开,并且新增了黑色标记的对象引用,导致该对象应该被扫描但是被错过了。 + + +研究表明出现第二个无法容忍的错误需要满足以下两个条件 +1. 赋值器插入一条或者多条从黑色对象到白色对象的引用。 +2. 赋值器删除了全部从灰色对象到该白色对象的直接或者间接引用。 + + +所以解决方案也由两个,只需要破坏其中的一个条件即可。 +1. 增量更新。破坏第一个条件,当黑色对象插入新的指向白色对象的引用关系时,就将这个新插入的引用记录下来,等并发扫描结束后,再将这些记录过的引用关系中的黑色对象为根,重新进行一次扫描。即,黑色对象一旦插入了白色对象的引用之后,就会变回灰色对象了。 + +2. 原始快照。破坏第二个条件。当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束后,再将这些记录过的应用关系中的灰色对象为根,重新扫描一次。即,无论关系是否删除,都会按照刚开始扫描那一刻的对象图来快照进行搜索。 + + +另外,虚拟机的记录操作都是通过写屏障实现的。CMS基于增量更新来做并发表及,G1和Shenandoah基于原始快照来实现。 +## 3.5 经典垃圾收集器 + +![垃圾收集器关系](image/2025-09-02T14:10:22.305Z.png) + +### Serial收集器 + +![Serial收集器](image/2025-09-02T14:10:34.665Z.png) + +算法对年轻一代使用mark-copy ,对老一代使用mark-sweep-compact 。 它在单个线程上工作。 执行时,它将冻结所有其他线程,直到垃圾回收操作结束。由于串行垃圾回收具有线程冻结特性,因此仅适用于非常小的程序。要使用串行GC,请使用以下JVM参数: +```java +-XX:+UseSerialGC +``` + + +特点: +1. 单线程工作收集器。垃圾收集时必须暂停其他所有工作线程,直到它收集结束。 +2. 简单有效,额外消耗最小的收集器。由于没有现成交互的开销,专心做垃圾收集可以获得最高的单线程收集效率。 + +应用场景 +1. 桌面引用场景或者部分微服务应用中,分配给虚拟机的内存一般不会太大。可以容忍一百毫秒以上的垃圾收集延迟。 + + + +### Parallel收集器 + +![Parallel](image/2025-09-02T14:19:00.028Z.png) + +与串行GC相似,它在年轻代中使用mark-copy ,在老年代中使用mark-sweep-compact 。 多个并发线程用于标记和复制/压缩阶段。 您可以使用-XX:ParallelGCThreads=N选项配置线程数。如果您的主要目标是通过有效利用现有系统资源来提高吞吐量,那么Parallel Garbage Collector将适用于多核计算机。 使用这种方法,可以大大减少GC循环时间。 +```java +-XX:+UseParallelGC +``` + +可以使用一下两个参数精确的控制吞吐量 +``` +-XX:MaxGCPauseMills:最大 GC 停顿的秒数; +-XX:GCTimeRatio 用户期望虚拟机消耗在GC上的时间不超过程序运行时间的1/(1+N),默认值为99。 +-XX:+UseAdaptiveSizePolicy:一个开关参数,打开后就无需手工指定 -Xmn,-XX:SurvivorRatio 等参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,自行调整。 +``` + +特点: +* 吞吐量优先。,其他收集器关注于尽可能缩短垃圾收集时用户线程的停顿时间,而 Parallel Scavenge 收集器的目的是达到一个可控的吞吐量。 + + +吞吐量 = 运行用户代码时间 / ( 运行用户代码时间 + 垃圾收集时间 ) + +适用场景 +* Parallel Scavenge 收集器不管是新生代还是老年代都是多个线程同时进行垃圾收集,十分适合于应用在注重吞吐量以及 CPU 资源敏感的场合。 + +### ParNew+CMS收集器 + +![Parnew young](image/2025-09-02T14:15:02.924Z.png) + +ParNew收集器支持多线程并行,同时使用多条线程进行垃圾收集。一般搭配在服务端使用。 + +特点: +* 标记复制算法。 + + + +![总结](image/2025-09-02T14:49:03.392Z.png) + + + +CMS垃圾回收实质上是一种升级的标记-清除方法。 它using multiple threads扫描堆内存。 对其进行了修改,以利用更快的系统并增强了性能。它尝试通过与应用程序线程concurrently执行大多数垃圾回收工作来最大程度地减少由于垃圾回收导致的​​暂停。 它在年轻一代中使用并行的世界停止mark-copy算法,而在老一代中使用大多数并发的mark-sweep算法。 +```java +-XX:+UseConcMarkSweepGC +-XX:+UseCMSCompactAtFullCollection:在 CMS 要进行 Full GC 时进行内存碎片整理(默认开启) +-XX:CMSFullGCsBeforeCompaction:在多少次 Full GC 后进行一次空间整理(默认是 0,即每一次 Full GC 后都进行一次空间整理) +``` + +特点: +1. 以获取最短回收停顿时间为目标的收集器。 +2. 标记清除算法 + +适用场景: +1. 互联网站的服务端上。关注服务的响应速度。停顿时间尽可能短,以给客户较好体验。 + + +运行原理 +![CMS收集器](image/2025-09-02T14:20:07.635Z.png) + +它是初始且非常基本的算法,分为两个阶段运行: + +* Marking live objects –找出所有仍然存在的对象。 +* Removing unreachable objects -摆脱所有其他东西-所谓的已死和未使用的对象。 + +第一阶段介绍: +1. mark live objects。首先,GC将某些特定对象定义为“ Garbage Collection Roots 。 例如,当前执行方法的局部变量和输入参数,活动线程,已加载类的静态字段和JNI引用。 现在,GC遍历了内存中的整个对象图,从这些根开始,然后是从根到其他对象的引用。 GC访问的每个对象都被标记为活动对象。 + + +第二阶段介绍 +1. mark-sweep。Normal deletion 普通删除将未引用的对象删除以释放空间并保留引用的对象和指针。 内存分配器(某种哈希表)保存对可分配新对象的可用空间块的引用。它通常被称为mark-sweep算法。 +![](image/2022-12-19-17-29-01.png) + +1. mark-sweep-compact 。Deletion with compacting仅删除未使用的对象效率不高,因为可用内存块分散在整个存储区域中,并且如果创建的对象足够大且找不到足够大的内存块,则会导致OutOfMemoryError 。为了解决此问题,删除未引用的对象后,将对其余的引用对象进行压缩。 这里的压缩指的是将参考对象一起移动的过程。 这使得新的内存分配变得更加容易和快捷。它通常被称为mark-sweep-compact算法。 +![](image/2022-12-19-17-29-28.png) + + +4. mark-copy 。Deletion with copying –与标记和补偿方法非常相似,因为它们也会重新放置所有活动对象。 重要的区别是重定位的目标是不同的存储区域。它通常被称为mark-copy算法。 +![](image/2022-12-19-17-29-53.png) + + + + +### G1收集器 + +![G1](image/2025-09-02T14:51:03.443Z.png) + +G1(垃圾优先)垃圾收集器已在Java 7中提供,旨在长期替代CMS收集器。 G1收集器是并行的,并发的,渐进压缩的低暂停垃圾收集器。此方法涉及将内存堆分段为多个小区域(通常为2048)。 每个区域都被标记为年轻一代(进一步划分为伊甸园地区或幸存者地区)或老一代。 这样,GC可以避免立即收集整个堆,而可以逐步解决问题。 这意味着一次只考虑区域的一个子集。 + +![原理](image/2025-09-02T14:51:42.247Z.png) + +特点 +1. G1跟踪每个区域包含的实时数据量。 此信息用于确定包含最多垃圾的区域。 因此它们是首先收集的。 +2. 这就是为什么它是名称garbage-first集合。与其他算法一样,不幸的是,压缩操作是使用Stop the World方法进行的。 但是根据其设计目标,您可以为其设置特定的性能目标。 您可以配置暂停持续时间,例如在任何给定的秒内不超过10毫秒。 垃圾优先GC将尽最大可能(但不能确定,由于OS级线程管理,这很难实时实现)来尽力实现该目标。 + +![](image/2022-12-19-17-34-47.png) + + +控制参数: +```java +-XX:+UseG1GC + +-XX:G1HeapRegionSize=16m based on the minimum Java heap size. +-XX:MaxGCPauseMillis=200 +-XX:G1ReservePercent=5 +-XX:GCPauseIntervalMillis=200 +``` + +## 3.6 更高效的收集器 +### ZGC + +1. 内存占用、吞吐量、延迟不可能三角。 + +## 3.7 选择合适的收集器 + +### 如何选择 + +![非常好的图](image/2025-09-02T14:45:33.404Z.png) +### GC日志分析 + +![GC日志分析](image/2025-09-02T14:53:27.434Z.png) + + +## 内存分配与回收策略 +自动内存管理主要包括两部分:自动给对象分配内存和自动回收分配给对象的内存。 +以下是最基本的内存分配原则: +### 对象优先在Eden中分配 + +1. 大多数情况下对象在Eden中分配。 +2. 当Eden没有足够的空间进行分配时,虚拟机将发起一次MinorGC + +### 大对象直接进入老年代 + +1. 需要大量连续内存空间的对象直接进入老年代。很长的字符串或者元素数量很庞大的数组。 +2. 因为如果分配在年轻代会进行标记复制算法,导致大对象在Eden和Survior区之间来回复制。 + +### 长期存活的对象进入老年代 + +1. 每个对象都有年龄计数器,在对象头中。每熬过一次minorGC年龄就会增加1 +2. 当年龄增加到15时,就会被晋升到老年代。可以通过-XX:MaxTenuringThreshold=15设置。 + +### 动态对象年龄判断 +1. 当Survior区中低于或等于某年龄的所有对象总和大于Survivor空间的一半,大于等于该年龄的对象就可以直接进入老年代。 + +### 空间分配担保 +风险:新生代使用标记复制收集算法。需要留有足够的空间,但是如果情况非常不理想所有的对象都存活则需要老年代有足够的空间担保能够完全存下Eden区。 + + +1. MinorGC虚拟机必须先检查老年代中最大可用的连续空间是否大于新生代所有对象的总空间。如果条件成立则MinorGC可以确保是安全的。 +2. 如果不成立,则虚拟机会先查看-XX:HandlePromotionFailure参数的设置值是否允许担保失败。如果允许会检查最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,则进行MinorGC,但需要冒风险。 +3. 否则进行FullGC + +## 总结 +* 对象生命周期分为三个阶段,即对象创建,对象使用和对象销毁。 +* mark-sweep , mark-sweep-compact和mark-copy机制如何工作。 +* 不同的单线程和并发GC算法。 +* 直到Java 8,并行GC才是默认算法。 +* 从Java 9开始,将G1设置为默认GC算法。 diff --git a/Java/JVM原理/02 Java类加载机制.md b/Java/07JVM编译原理/07 Java类加载机制.md similarity index 100% rename from Java/JVM原理/02 Java类加载机制.md rename to Java/07JVM编译原理/07 Java类加载机制.md diff --git a/Java/JVM原理/Java 虚拟机.md b/Java/07JVM编译原理/Java 虚拟机.md similarity index 100% rename from Java/JVM原理/Java 虚拟机.md rename to Java/07JVM编译原理/Java 虚拟机.md diff --git a/Java/01Java语言基础/image/2022-12-04-13-14-56.png b/Java/07JVM编译原理/image/2022-12-04-13-14-56.png similarity index 100% rename from Java/01Java语言基础/image/2022-12-04-13-14-56.png rename to Java/07JVM编译原理/image/2022-12-04-13-14-56.png diff --git a/Java/01Java语言基础/image/2022-12-04-13-15-46.png b/Java/07JVM编译原理/image/2022-12-04-13-15-46.png similarity index 100% rename from Java/01Java语言基础/image/2022-12-04-13-15-46.png rename to Java/07JVM编译原理/image/2022-12-04-13-15-46.png diff --git a/Java/JVM原理/image/2022-12-19-17-08-55.png b/Java/07JVM编译原理/image/2022-12-19-17-08-55.png similarity index 100% rename from Java/JVM原理/image/2022-12-19-17-08-55.png rename to Java/07JVM编译原理/image/2022-12-19-17-08-55.png diff --git a/Java/JVM原理/image/2022-12-19-17-19-40.png b/Java/07JVM编译原理/image/2022-12-19-17-19-40.png similarity index 100% rename from Java/JVM原理/image/2022-12-19-17-19-40.png rename to Java/07JVM编译原理/image/2022-12-19-17-19-40.png diff --git a/Java/JVM原理/image/2022-12-19-17-29-01.png b/Java/07JVM编译原理/image/2022-12-19-17-29-01.png similarity index 100% rename from Java/JVM原理/image/2022-12-19-17-29-01.png rename to Java/07JVM编译原理/image/2022-12-19-17-29-01.png diff --git a/Java/JVM原理/image/2022-12-19-17-29-28.png b/Java/07JVM编译原理/image/2022-12-19-17-29-28.png similarity index 100% rename from Java/JVM原理/image/2022-12-19-17-29-28.png rename to Java/07JVM编译原理/image/2022-12-19-17-29-28.png diff --git a/Java/JVM原理/image/2022-12-19-17-29-53.png b/Java/07JVM编译原理/image/2022-12-19-17-29-53.png similarity index 100% rename from Java/JVM原理/image/2022-12-19-17-29-53.png rename to Java/07JVM编译原理/image/2022-12-19-17-29-53.png diff --git a/Java/JVM原理/image/2022-12-19-17-34-47.png b/Java/07JVM编译原理/image/2022-12-19-17-34-47.png similarity index 100% rename from Java/JVM原理/image/2022-12-19-17-34-47.png rename to Java/07JVM编译原理/image/2022-12-19-17-34-47.png diff --git a/Java/07JVM编译原理/image/2025-08-13T14:44:27.336Z.png b/Java/07JVM编译原理/image/2025-08-13T14:44:27.336Z.png new file mode 100644 index 00000000..2eb3198e Binary files /dev/null and b/Java/07JVM编译原理/image/2025-08-13T14:44:27.336Z.png differ diff --git a/Java/07JVM编译原理/image/2025-08-17T11:54:09.045Z.png b/Java/07JVM编译原理/image/2025-08-17T11:54:09.045Z.png new file mode 100644 index 00000000..672dd8bb Binary files /dev/null and b/Java/07JVM编译原理/image/2025-08-17T11:54:09.045Z.png differ diff --git a/Java/07JVM编译原理/image/2025-08-17T13:03:25.913Z.png b/Java/07JVM编译原理/image/2025-08-17T13:03:25.913Z.png new file mode 100644 index 00000000..91bbee59 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-08-17T13:03:25.913Z.png differ diff --git a/Java/07JVM编译原理/image/2025-08-17T13:04:27.869Z.png b/Java/07JVM编译原理/image/2025-08-17T13:04:27.869Z.png new file mode 100644 index 00000000..1e19a0a8 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-08-17T13:04:27.869Z.png differ diff --git a/Java/07JVM编译原理/image/2025-08-17T13:04:41.104Z.png b/Java/07JVM编译原理/image/2025-08-17T13:04:41.104Z.png new file mode 100644 index 00000000..5c72c866 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-08-17T13:04:41.104Z.png differ diff --git a/Java/07JVM编译原理/image/2025-08-17T13:04:58.569Z.png b/Java/07JVM编译原理/image/2025-08-17T13:04:58.569Z.png new file mode 100644 index 00000000..b00aa3a9 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-08-17T13:04:58.569Z.png differ diff --git a/Java/07JVM编译原理/image/2025-08-17T13:08:54.326Z.png b/Java/07JVM编译原理/image/2025-08-17T13:08:54.326Z.png new file mode 100644 index 00000000..2f415c66 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-08-17T13:08:54.326Z.png differ diff --git a/Java/07JVM编译原理/image/2025-08-17T13:09:12.527Z.png b/Java/07JVM编译原理/image/2025-08-17T13:09:12.527Z.png new file mode 100644 index 00000000..26c1d1b4 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-08-17T13:09:12.527Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:10:22.305Z.png b/Java/07JVM编译原理/image/2025-09-02T14:10:22.305Z.png new file mode 100644 index 00000000..bf9e0be3 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:10:22.305Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:10:34.665Z.png b/Java/07JVM编译原理/image/2025-09-02T14:10:34.665Z.png new file mode 100644 index 00000000..a1e0bd97 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:10:34.665Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:15:02.924Z.png b/Java/07JVM编译原理/image/2025-09-02T14:15:02.924Z.png new file mode 100644 index 00000000..11983299 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:15:02.924Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:19:00.028Z.png b/Java/07JVM编译原理/image/2025-09-02T14:19:00.028Z.png new file mode 100644 index 00000000..22c15434 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:19:00.028Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:20:07.635Z.png b/Java/07JVM编译原理/image/2025-09-02T14:20:07.635Z.png new file mode 100644 index 00000000..f8cbb4da Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:20:07.635Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:45:33.404Z.png b/Java/07JVM编译原理/image/2025-09-02T14:45:33.404Z.png new file mode 100644 index 00000000..9de793ad Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:45:33.404Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:49:03.392Z.png b/Java/07JVM编译原理/image/2025-09-02T14:49:03.392Z.png new file mode 100644 index 00000000..756b1fc0 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:49:03.392Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:51:03.443Z.png b/Java/07JVM编译原理/image/2025-09-02T14:51:03.443Z.png new file mode 100644 index 00000000..ef70108e Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:51:03.443Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:51:42.247Z.png b/Java/07JVM编译原理/image/2025-09-02T14:51:42.247Z.png new file mode 100644 index 00000000..d88c84bc Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:51:42.247Z.png differ diff --git a/Java/07JVM编译原理/image/2025-09-02T14:53:27.434Z.png b/Java/07JVM编译原理/image/2025-09-02T14:53:27.434Z.png new file mode 100644 index 00000000..396fe814 Binary files /dev/null and b/Java/07JVM编译原理/image/2025-09-02T14:53:27.434Z.png differ diff --git a/Java/JVM原理/jvm gc机制说明.md b/Java/07JVM编译原理/jvm gc机制说明.md similarity index 100% rename from Java/JVM原理/jvm gc机制说明.md rename to Java/07JVM编译原理/jvm gc机制说明.md diff --git a/Java/JVM原理/03 Java垃圾回收机制.md b/Java/JVM原理/03 Java垃圾回收机制.md deleted file mode 100644 index 7c1adae0..00000000 --- a/Java/JVM原理/03 Java垃圾回收机制.md +++ /dev/null @@ -1,177 +0,0 @@ -## 1 JVM Memory Model - -### JVM内存模型和结构 - -Java虚拟机定义了在程序执行期间使用的各种run-time data areas 。 其中一些数据区域是在Java虚拟机启动时创建的,仅在Java虚拟机退出时才被销毁。 其他数据区域是每个线程的。 在创建线程时创建每个线程的数据区域,并在线程退出时销毁每个数据区域。 - -![](image/2022-12-19-17-08-55.png) - -### 堆区Heap Area - -堆区代表运行时数据区,从中为所有类实例和数组分配内存,并在虚拟机启动期间创建。 - -自动存储管理系统回收对象的堆存储。 堆的大小可以是固定的或动态的(基于系统的配置),并且分配给堆区域的内存不必是连续的。 - -### 方法区Method Area - -方法区域存储每个类的结构,例如运行时常量池; 领域和方法数据; 方法和构造函数的代码,包括用于类,实例和接口初始化的特殊方法。 - -方法区域是在虚拟机启动时创建的。 尽管从逻辑上讲它是堆的一部分,但是可以或不能将其进行垃圾收集,而我们已经读到堆中的垃圾收集不是可选的; 这是强制性的。 方法区域可以是固定大小的,或者可以根据计算的需要进行扩展,如果不需要更大的方法区域,则可以缩小。 方法区域的内存不必是连续的。 - -### 堆栈区JVM Stacks -每个JVM线程都有一个与该线程同时创建的私有堆栈。 堆栈存储帧。 框架用于存储数据和部分结果,并执行动态链接,方法的返回值和调度异常。 - -它保存局部变量和部分结果,并在方法调用和返回中起作用。 因为除了压入和弹出帧外,从不直接操纵此堆栈,所以可以对帧进行堆分配。 与堆类似,此堆栈的内存不必是连续的。 - -该规范允许堆栈的大小可以是固定的,也可以是动态的。 如果具有固定大小,则在创建该堆栈时可以独立选择每个堆栈的大小。 - -### 原生堆栈Native method stacks -本机方法堆栈称为C堆栈; 它支持本机方法(用Java编程语言以外的其他语言编写的方法),通常在创建每个线程时为每个线程分配。 无法加载本机方法并且自身不依赖于常规堆栈的Java虚拟机实现不需要提供本机方法堆栈。 - -本机方法堆栈的大小可以是固定的,也可以是动态的。 - - -### PC registers -每个JVM线程都有其自己的程序计数器(pc)寄存器。 在任何时候,每个JVM线程都在执行单个方法的代码,即该线程的当前方法。 - -由于Java应用程序可以包含一些本机代码(例如,使用本机库),因此本机和非本机方法有两种不同的方式。 如果该方法不是本机的(即Java代码),则PC寄存器包含当前正在执行的JVM指令的地址。 如果该方法是本地方法,则未定义JVM的PC寄存器的值。 - -Java虚拟机的pc寄存器足够宽,可以在特定平台上保存返回地址或本机指针。 - - -## 2 Java 内存管理Memory management - -### GC概念 - -Java中的Memory management是垃圾收集器的职责。 - -* allocating memory -* 确保所有引用的对象都保留在内存中,并且 -* 恢复由执行代码中的引用无法访问的对象使用的内存。 - - -在应用程序运行时,应用程序会创建许多对象,每个对象都有其生命周期。 在内存中,被其他对象引用的对象被称为live objects 。 不再由任何活动对象引用的对象被视为dead objects ,并称为garbage 。 查找和释放(也称为回收)这些对象使用的空间的过程称为garbage collection 。 - - -垃圾回收解决了许多但不是全部的内存分配问题。 例如,我们可以无限期地创建对象并继续引用它们,直到没有更多可用内存为止( Out of memory error )。 垃圾收集是一项复杂的任务,需要花费时间和资源。 它在通常由称为堆的大型内存池分配的空间上运行。 - -垃圾收集的时间取决于垃圾收集器。 通常,整个堆或堆的一部分会在堆满或达到占用率的百分比时收集。 - -### 引用计数机制Reference counting mechanism - -非常古老的GC机制。 在引用计数技术中,每个对象都有从其他对象和堆栈指向该对象的指针数。 每次引用新对象时,计数器都会增加一。 同样,当任何对象丢失其引用时,计数器将减一。 当count达到'0'时,垃圾回收器可以取消分配对象。 - - -引用计数算法的主要advantage是分配给新对象时每次内存写入工作量少。 但是,它在data cycles方面存在非常critical problem 。 这意味着当第一个对象被第二个对象引用,第二个对象被第一个对象( cyclic references ) cyclic references ,计数永远不会为零,因此它们永远不会被垃圾回收。 - -### 标记清除机制Mark and sweep mechanism - -![](image/2022-12-19-17-19-40.png) - -标记清除算法是第一个开发的able to reclaim cyclic data structures垃圾收集算法。 在这种算法中,GC将首先将某些对象标识为默认可达对象,这些对象通常是堆栈中的全局变量和局部变量。 有所谓的活动对象。 - -在下一步中,算法开始从这些活动对象中跟踪对象,并将它们也标记为活动对象。 继续执行此过程,直到检查所有对象并将其标记为活动。 完全跟踪后未标记为活动的对象被视为死对象。 - -使用标记扫描时,未引用的对象不会立即被回收。 取而代之的是,允许垃圾收集累积,直到所有可用内存都用完为止。 发生这种情况时,该程序的执行会暂时暂停(这称为stop the world ),而标记清除算法会收集所有垃圾。 一旦回收了所有未引用的对象,就可以恢复程序的正常执行。 - -除了暂停应用程序一段时间外,该技术还需要经常对内存地址空间de-fragmentation整理,这是另一项开销。 - - -### 停止copy机制Stop and copy GC -像“标记和清除”一样,该算法还取决于识别活动对象并对其进行标记。 区别在于它处​​理活动对象的方式。 - -停止和复制技术将整个堆设计为两个semi-spaces 。 一次只有一个半空间处于活动状态,而为新创建的对象分配的内存仅发生在单个半空间中,而另一个保持平静。 - -GC运行时,它将开始标记当前半空间中的活动对象,完成后,它将所有活动对象复制到其他半空间中。 当前半空间中的所有其余对象都被视为已死,并已被垃圾回收。 - -与以前的方法一样,它具有一些advantages例如仅接触活动对象。 另外,不需要分段,因为在切换半memory contraction会完成memory contraction 。 - -这种方法的主要disadvantages是需要将所需的内存大小增加一倍,因为在给定的时间点仅使用一半的内存。 除此之外,它还需要在切换半空间时停止世界。 - - -### 世代停止复制机制Generational stop and copy - - -将内存划分为三个半空间。 这些半空间在这里称为世代。 因此,此技术中的内存分为三代: young generation , old generation和permanent generation 。 - -大多数对象最初是在年轻一代中分配的。 老一代包含的对象在许多年轻一代集合中幸存下来,还有一些大型对象可以直接在老一代中分配。 永久生成包含JVM认为便于垃圾回收器管理的对象,例如描述类和方法的对象,以及类和方法本身。 - -当年轻一代填满时,将执行该一代的年轻一代垃圾收集(有时称为minor collection垃圾minor collection )。 当旧的或永久的一代填满时,通常会完成所谓的完整垃圾回收(有时称为major collection垃圾major collection )。 即,收集了所有的世代。 - -通常,首先使用专门为该代设计的垃圾收集算法来收集年轻代,因为它通常是识别年轻代中最有效的垃圾算法。 幸存于GC跟踪中的对象被推入更早的年代。 出于明显的原因,较老的一代被收集的频率较低,即它们在那里是因为时间更长。 除上述情况外,如果发生碎片/压缩,则每一代都将单独压缩。 - -该技术的主要advantages是可以在较年轻的一代中早期回收死对象,而无需每次都扫描整个内存以识别死对象。 较早的对象已经经历了一些GC周期,因此假定它们在系统中的存在时间更长,因此无需频繁扫描它们(不是每次都完美的情况,但大多数情况下应该如此)。 - -Disadvantages还是一样,即需要对存储区进行碎片整理,并且需要在GC运行全扫描时停止整个环境(应用程序) - - - - -## 3 垃圾回收的策略 - -### mark and sweep标记清除算法 - -它是初始且非常基本的算法,分为两个阶段运行: - -* Marking live objects –找出所有仍然存在的对象。 -* Removing unreachable objects -摆脱所有其他东西-所谓的已死和未使用的对象。 - -第一阶段介绍: -1. mark live objects。首先,GC将某些特定对象定义为“ Garbage Collection Roots 。 例如,当前执行方法的局部变量和输入参数,活动线程,已加载类的静态字段和JNI引用。 现在,GC遍历了内存中的整个对象图,从这些根开始,然后是从根到其他对象的引用。 GC访问的每个对象都被标记为活动对象。 - - -第二阶段介绍 -1. mark-sweep。Normal deletion 普通删除将未引用的对象删除以释放空间并保留引用的对象和指针。 内存分配器(某种哈希表)保存对可分配新对象的可用空间块的引用。它通常被称为mark-sweep算法。 -![](image/2022-12-19-17-29-01.png) - -1. mark-sweep-compact 。Deletion with compacting仅删除未使用的对象效率不高,因为可用内存块分散在整个存储区域中,并且如果创建的对象足够大且找不到足够大的内存块,则会导致OutOfMemoryError 。为了解决此问题,删除未引用的对象后,将对其余的引用对象进行压缩。 这里的压缩指的是将参考对象一起移动的过程。 这使得新的内存分配变得更加容易和快捷。它通常被称为mark-sweep-compact算法。 -![](image/2022-12-19-17-29-28.png) - - -4. mark-copy 。Deletion with copying –与标记和补偿方法非常相似,因为它们也会重新放置所有活动对象。 重要的区别是重定位的目标是不同的存储区域。它通常被称为mark-copy算法。 -![](image/2022-12-19-17-29-53.png) - -### Concurrent mark sweep (CMS) - -CMS垃圾回收实质上是一种升级的标记和清除方法。 它using multiple threads扫描堆内存。 对其进行了修改,以利用更快的系统并增强了性能。它尝试通过与应用程序线程concurrently执行大多数垃圾回收工作来最大程度地减少由于垃圾回收导致的​​暂停。 它在年轻一代中使用并行的世界停止mark-copy算法,而在老一代中使用大多数并发的mark-sweep算法。 -```java --XX:+UseConcMarkSweepGC -``` - - -### Serial garbage collection - -该算法对年轻一代使用mark-copy ,对老一代使用mark-copy mark-sweep-compact 。 它在单个线程上工作。 执行时,它将冻结所有其他线程,直到垃圾回收操作结束。由于串行垃圾回收具有线程冻结特性,因此仅适用于非常小的程序。要使用串行GC,请使用以下JVM参数: -```java --XX:+UseSerialGC -``` - -### Parallel garbage collection - -与串行GC相似,它在年轻一代中使用mark-copy ,在旧一代中使用mark-sweep-compact 。 多个并发线程用于标记和复制/压缩阶段。 您可以使用-XX:ParallelGCThreads=N选项配置线程数。如果您的主要目标是通过有效利用现有系统资源来提高吞吐量,那么Parallel Garbage Collector将适用于多核计算机。 使用这种方法,可以大大减少GC循环时间。 -```java --XX:+UseParallelGC -``` - -### G1 garbage collection - -G1(垃圾优先)垃圾收集器已在Java 7中提供,旨在长期替代CMS收集器。 G1收集器是并行的,并发的,渐进压缩的低暂停垃圾收集器。此方法涉及将内存堆分段为多个小区域(通常为2048)。 每个区域都被标记为年轻一代(进一步划分为伊甸园地区或幸存者地区)或老一代。 这样,GC可以避免立即收集整个堆,而可以逐步解决问题。 这意味着一次只考虑区域的一个子集。 - 1. G1跟踪每个区域包含的实时数据量。 此信息用于确定包含最多垃圾的区域。 因此它们是首先收集的。 - 2. 这就是为什么它是名称garbage-first集合。与其他算法一样,不幸的是,压缩操作是使用Stop the World方法进行的。 但是根据其设计目标,您可以为其设置特定的性能目标。 您可以配置暂停持续时间,例如在任何给定的秒内不超过10毫秒。 垃圾优先GC将尽最大可能(但不能确定,由于OS级线程管理,这很难实时实现)来尽力实现该目标。 -![](image/2022-12-19-17-34-47.png) - -```java --XX:+UseG1GC - --XX:G1HeapRegionSize=16m based on the minimum Java heap size. --XX:MaxGCPauseMillis=200 --XX:G1ReservePercent=5 --XX:GCPauseIntervalMillis=200 -``` - -### 总结 -* 对象生命周期分为三个阶段,即对象创建,对象使用和对象销毁。 -* mark-sweep , mark-sweep-compact和mark-copy机制如何工作。 -* 不同的单线程和并发GC算法。 -* 直到Java 8,并行GC才是默认算法。 -* 从Java 9开始,将G1设置为默认GC算法。 diff --git a/Rust/01 Rust核心语法/01 数据类型和变量.md b/Rust/01 Rust核心语法/01 数据类型和变量.md new file mode 100644 index 00000000..8d60932c --- /dev/null +++ b/Rust/01 Rust核心语法/01 数据类型和变量.md @@ -0,0 +1,210 @@ +## 如何速通各种语言 + +![如何速通](image/2025-08-21T02:34:52.388Z.png) + +一个语言应该包括以下几个部分 + +* 核心语法:数据类型和变量、控制流程、数据结构、函数、面向对象、其他 +* 内置工具库:数学、日期、字符串、系统、序列化等 +* 内置高阶库:文件IO、网络编程、并发编程 +* 生态库:Web框架、客户端、分布式 +* 编译原理:虚拟机 + +## 安装 + +1. 安装rustup,用来管理rust版本的工具。 +```sh +$ curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh +``` +2. 安装更新rust +``` +rustup update +``` +3. 查看安装的版本 +``` +rustc --version +``` + +## 优势分析 + +1. 所有权\move语法\借用引用 +2. 表达式与语句概念 + + +## 变量 + +### 变量和常量 +1. 默认情况下是不可变的。这也是rust的设计哲学之一:通过默认的方式避免掉了很多种可能会出现的错误,非常好的设计思路,将最稳定、最安全的方式作为默认的方式。 +2. 可变变量使用mut关键字修饰。 +``` +let mut x = 5; +x =6; +``` +3. 常量使用const关键字修饰。必须在声明的时候初始化,只能是字面常量或者常量表达式,不能是函数调用结果,因为要在编译阶段计算常量的值。常量可以在任意作用域内声明,包括全局作用域,这对于代码中很多部分都需要知道一个值的情况特别有用。 +``` +const X:i32 = 5; +``` +4. 变量遮蔽。可以声明和前面变量具有相同名称的新变量。通过使用相同的变量名并重复使用 let 关键字来遮蔽变量。其实变量遮蔽功能跟变量支持重复赋值功能已经没有什么区别了,但是换了一个概念,就解决了内存管理的问题,太厉害了。 + 1. mut和变量遮蔽不同。变量遮蔽可以讲变量声明为不同的类型。而且新的变量有自己的地址。 +``` +fn main() { + let x = 5; + + let x = x + 1; + + { + let x = x * 2; + println!("The value of x in the inner scope is: {}", x); + } + + println!("The value of x is: {}", x); +} +``` + + +## 数据类型 + +### 数据类型的规则 + +Rust 是一种静态类型(statically typed)的语言,每个值都有确切的数据类型(data type),必须在编译期知道所有变量的类型。 + + +标量(scalar)类型表示单个值。Rust 有 4 个基本的标量类型:整型、浮点型、布尔型和字符。 + +### 整型 +整型。每个定义形式要么是有符号类型要么是无符号类型,且带有一个显式的大小。有符号和无符号表示数字能否取负数——也就是说,这个数是否可能是负数(有符号类型),或一直为正而不需要带上符号(无符号类型)。就像在纸上写数字一样:当要强调符号时,数字前面可以带上正号或负号;然而,当很明显确定数字为正数时,就不需要加上正号了。有符号数字以二进制补码(译者补充:“补码”百度百科)形式存储。 +``` +8 位 i8 u8 +16 位 i16 u16 +32 位 i32 u32 +64 位 i64 u64 +128 位 i128 u128 +arch isize usize +``` +Rust 的整型字面量 +``` +数字字面量 示例 +十进制 98_222 +十六进制 0xff +八进制 0o77 +二进制 0b1111_0000 +字节 (仅限于 u8) b'A' +``` +Rust 的所有数字类型都支持基本数学运算:加法、减法、乘法、除法和取模运算。整数除法会向下取整。 + +### 浮点类型 +浮点数(floating-point number)是带有小数点的数字,在 Rust 中浮点类型(简称浮点型)数字也有两种基本类型。Rust 的浮点型是 f32 和 f64,它们的大小分别为 32 位和 64 位。 + + +``` +fn main() { + let x = 2.0; // f64 + + let y: f32 = 3.0; // f32 +} +``` + +### 布尔类型 +和大多数编程语言一样,Rust 中的布尔类型也有两个可能的值:true 和 false。布尔值的大小为 1 个字节。Rust 中的布尔类型使用 bool 声明。 + +```rs +fn main() { + let t = true; + + let f: bool = false; // with explicit type annotation +} +``` + +### 复合类型-元祖 + +复合类型(compound type)可以将多个值组合成一个类型。Rust 有两种基本的复合类型:元组(tuple)和数组(array)。 + + +元组是将多种类型的多个值组合到一个复合类型中的一种基本方式。元组的长度是固定的:声明后,它们就无法增长或缩小。 + +元组中的每个位置都有一个类型,并且元组中不同值的类型不要求是相同的。 +```rs +fn main() { + let tup: (i32, f64, u8) = (500, 6.4, 1); +} +``` +使用模式匹配来解构(destructure)元组的一个值 +```rs +fn main() { + let tup = (500, 6.4, 1); + + let (x, y, z) = tup; + + println!("The value of y is: {}", y); +} +``` +使用一个句点(.)连上要访问的值的索引来直接访问元组元素。 +```rs +fn main() { + let x: (i32, f64, u8) = (500, 6.4, 1); + + let five_hundred = x.0; + + let six_point_four = x.1; + + let one = x.2; +} +``` + +### 复合类型-数组 + +将多个值组合在一起的另一种方式就是使用数组(array)。与元组不同,数组的每个元素必须具有相同的类型。与某些其他语言中的数组不同,Rust 中的数组具有固定长度。 +```rs +fn main() { + // 直接初始化 + let a = [1, 2, 3, 4, 5]; + // 隐含的类型 + let a: [i32; 5] = [1, 2, 3, 4, 5]; + // 重复元素初始化 + let a = [3; 5]; + +} +``` + + + + + +## 注释 + +```rust +// Hello, world. + +fn main() { + let lucky_number = 7; // I’m feeling lucky today +} +``` + + + +## 语句和表达式 + +> 这个设计也太舒服了,非常非常符合直觉且非常好用 + +所有的代码块都支持两种形式,语句或者表达式。语句就是执行一段代码,表达式就是返回一个值,表达式返回值的可以用于给变量赋值形成语句、用于循环的判断条件等。这里重点讲表达式。 + +1. 最简单的表达式 +```rust +5 + 6 //这是一个表达式 +a = 5 + 6; //这是一个利用表达式的赋值语句 +``` +2. 代码块表达式 +```rust +{ + let a = 5; + a +} //这是一个代码块表达式 + +test = { + let a = 5; + a +}; //这是一个表达式赋值语句 +``` +3. 函数表达式 +4. 条件语句表达式 +5. 宏表达式 diff --git a/Rust/01 Rust核心语法/02 控制流程.md b/Rust/01 Rust核心语法/02 控制流程.md new file mode 100644 index 00000000..3da23a14 --- /dev/null +++ b/Rust/01 Rust核心语法/02 控制流程.md @@ -0,0 +1,148 @@ +## if表达式 + +### 基本语句 +if 表达式允许根据条件执行不同的代码分支。你提供一个条件并表示 “如果条件满足,运行这段代码;如果条件不满足,不运行这段代码。” + +```rust +fn main() { + let number = 3; + + if number < 5 { + println!("condition was true"); + } else { + println!("condition was false"); + } +} +``` + +### elseif多重条件 + +可以将 if 和 else 组成的 else if 表达式来实现多重条件。例如: + +```rust +fn main() { + let number = 6; + + if number % 4 == 0 { + println!("number is divisible by 4"); + } else if number % 3 == 0 { + println!("number is divisible by 3"); + } else if number % 2 == 0 { + println!("number is divisible by 2"); + } else { + println!("number is not divisible by 4, 3, or 2"); + } +} +``` + +### 将if代码块视作表达式 + +在 let 语句中使用 if + +```rust +fn main() { + let condition = true; + + let number = if condition { 5 } else { 6 }; + + println!("The value of number is: {}", number); +} +``` + +## 循环表达式 + + +### loop循环 + +loop 关键字告诉 Rust 一遍又一遍地执行一段代码直到你明确要求停止。 + +* 循环中的 continue 关键字告诉程序跳过这个循环迭代中的任何剩余代码,并转到下一个迭代 +* 使用 break 关键字来告诉程序何时停止循环。 + + +循环标签:如果存在嵌套循环,break 和 continue 应用于此时最内层的循环。你可以选择在一个循环上指定一个循环标签(loop label),然后将标签与 break 或 continue 一起使用,使这些关键字应用于已标记的循环而不是最内层的循环。 + +```rust +fn main() { + let mut count = 0; + 'counting_up: loop { + println!("count = {}", count); + let mut remaining = 10; + + loop { + println!("remaining = {}", remaining); + if remaining == 9 { + break; + } + if count == 2 { + break 'counting_up; + } + remaining -= 1; + } + + count += 1; + } + println!("End count = {}", count); +} +``` + +从循环返回:loop 的一个用例是重试可能会失败的操作,比如检查线程是否完成了任务。然而你可能会需要将操作的结果从循环中传递给其它的代码。为此,你可以在用于停止循环的 break 表达式添加你想要返回的值; + +```rust +fn main() { + let mut counter = 0; + + let result = loop { + counter += 1; + + if counter == 10 { + break counter * 2; + } + }; + + println!("The result is {}", result); +} +``` + +### while循环 + +在程序中计算循环的条件也很常见。当条件为真,执行循环。当条件不再为真,调用 break 停止循环。 + +```rust +fn main() { + let mut number = 3; + + while number != 0 { + println!("{}!", number); + + number -= 1; + } + + println!("LIFTOFF!!!"); +} +``` +这种结构消除了很多使用 loop、if、else 和 break 时所必须的嵌套,这样更加清晰。当条件为真就执行,否则退出循环。 + +### for循环 + +可以使用 while 结构来遍历集合中的元素,比如数组。例如,示例 3-4 中的循环打印数组 a 中的每个元素。 + +```rust +fn main() { + let a = [10, 20, 30, 40, 50]; + + for element in a { + println!("the value is: {}", element); + } +} +``` + +for 循环的安全性和简洁性使得它成为 Rust 中使用最多的循环结构。即使是在想要循环执行代码特定次数时,例如示例 3-3 中使用 while 循环的倒计时例子,大部分 Rustacean 也会使用 for 循环。使用 Range,它是标准库提供的类型,用来生成从一个数字开始到另一个数字之前结束的所有数字的序列。for-range实例 +```rust +fn main() { + for number in (1..4).rev() { + println!("{}!", number); + } + println!("LIFTOFF!!!"); +} +``` diff --git a/Rust/01 Rust核心语法/03 数据结构.md b/Rust/01 Rust核心语法/03 数据结构.md new file mode 100644 index 00000000..0ae41806 --- /dev/null +++ b/Rust/01 Rust核心语法/03 数据结构.md @@ -0,0 +1,233 @@ +## 结构体 + +### 结构体定义 + +结构体和我们在“元组类型”章节论过的元组类似。和元组一样,结构体的每一部分可以是不同类型。但不同于元组,结构体需要命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字,结构体比元组更灵活:不需要依赖顺序来指定或访问实例中的值。 + +定义结构体,需要使用 struct 关键字并为整个结构体提供一个名字。结构体的名字需要描述它所组合的数据的意义。接着,在大括号中,定义每一部分数据的名字和类型,我们称为 字段(field)。例如,示例 5-1 展示了一个存储用户账号信息的结构体: + +```rust +struct User { + active: bool, + username: String, + email: String, + sign_in_count: u64, +} + +fn main() {} +``` + +### 结构体使用 +通过为每个字段指定具体值的方式来创建该结构体的实例。创建一个实例需要以结构体的名字开头,接着在大括号中使用 key: value 键-值对的形式提供字段,其中 key 是字段的名字,value 是需要存储在字段中的数据值。实例中字段的顺序不需要和它们在结构体中声明的顺序一致。换句话说,结构体的定义就像一个类型的通用模板,而实例则会在这个模板中放入特定数据来创建这个类型的值。 +```rust +struct User { + active: bool, + username: String, + email: String, + sign_in_count: u64, +} +``` +访问结构体中的数据,与元祖一样,通过.语法访问,元祖中feild是索引,而结构体中是feild的名称 +```rust +fn main() { + let user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, + }; + user1.email = String::from("anotheremail@example.com"); +} +``` +注意整个实例必须是可变的;Rust 并不允许只将某个字段标记为可变。另外需要注意同其他任何表达式一样,我们可以在函数体的最后一个表达式中构造一个结构体的新实例,来隐式地返回这个实例。 + +```rust +struct User { + active: bool, + username: String, + email: String, + sign_in_count: u64, +} + +fn build_user(email: String, username: String) -> User { + User { + email: email, + username: username, + active: true, + sign_in_count: 1, + } +} + +fn main() { + let user1 = build_user( + String::from("someone@example.com"), + String::from("someusername123"), + ); +} + +``` +参数名与字段名都完全相同,我们可以使用字段初始化简写语法 + +```rust +struct User { + active: bool, + username: String, + email: String, + sign_in_count: u64, +} + +fn build_user(email: String, username: String) -> User { + User { + email, + username, + active: true, + sign_in_count: 1, + } +} + +fn main() { + let user1 = build_user( + String::from("someone@example.com"), + String::from("someusername123"), + ); +} + +``` +### 结构体更新 + + +使用旧实例的大部分值但改变其部分值来创建一个新的结构体实例 +```rust +struct User { + active: bool, + username: String, + email: String, + sign_in_count: u64, +} + +fn main() { + // --snip-- + + let user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, + }; + + let user2 = User { + active: user1.active, + username: user1.username, + email: String::from("another@example.com"), + sign_in_count: user1.sign_in_count, + }; +} + +``` +使用结构体更新语法,我们可以通过更少的代码来达到相同的效果。.. 语法指定了剩余未显式设置值的字段应有与给定实例对应字段相同的值。 +```rust +struct User { + active: bool, + username: String, + email: String, + sign_in_count: u64, +} + +fn main() { + // --snip-- + + let user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, + }; + + let user2 = User { + email: String::from("another@example.com"), + ..user1 + }; +} +``` +代码还创建了一个新实例 user2,该实例具有不同的 email 值,但 username、 active 和 sign_in_count 字段的值与 user1 相同。..user1 必须放在最后,以指定其余的字段应从 user1 的相应字段中获取其值,但我们可以选择以任何顺序为任意字段指定值,而不用考虑结构体定义中字段的顺序。 + +结构更新语法就像带有 = 的赋值,因为它移动了数据,就像我们在“变量与数据交互的方式(一):移动”部分讲到的一样。在这个例子中,我们在创建 user2 后不能再使用 user1,因为 user1 的 username 字段中的 String 被移到 user2 中。如果我们给 user2 的 email 和 username 都赋予新的 String 值,从而只使用 user1 的 active 和 sign_in_count 值,那么 user1 在创建 user2 后仍然有效。 + + +## 其他结构体 +### 元组结构体 + + +使用没有命名字段的元组结构体来创建不同的类型 + +元组结构体有着结构体名称提供的含义,但没有具体的字段名,只有字段的类型。当你想给整个元组取一个名字,并使元组成为与其他元组不同的类型时,元组结构体是很有用的,这时像常规结构体那样为每个字段命名就显得多余和形式化了。 + +要定义元组结构体,以 struct 关键字和结构体名开头并后跟元组中的类型。例如,下面是两个分别叫做 Color 和 Point 元组结构体的定义和用法: + +```rust +struct Color(i32, i32, i32); +struct Point(i32, i32, i32); + +fn main() { + let black = Color(0, 0, 0); + let origin = Point(0, 0, 0); +} + +``` + + +### 类单元结构体 +我们也可以定义一个没有任何字段的结构体!它们被称为类单元结构体(unit-like structs),因为它们类似于 (),即“元组类型”一节中提到的 unit 类型。类单元结构体常常在你想要在某个类型上实现 trait 但不需要在类型中存储数据的时候发挥作用。我们将在第 10 章介绍 trait。下面是一个声明和实例化一个名为 AlwaysEqual 的 unit 结构的例子。 + +```rust +struct AlwaysEqual; + +fn main() { + let subject = AlwaysEqual; +} +``` + +## 结构体方法 + +### 定义 +方法 与函数类似:它们使用 fn 关键字和名称声明,可以拥有参数和返回值,同时包含在某处调用该方法时会执行的代码。不过方法与函数是不同的,因为它们在结构体的上下文中被定义。并且它们第一个参数总是 self,它代表调用该方法的结构体实例。 + +让我们把前面实现的获取一个 Rectangle 实例作为参数的 area 函数,改写成一个定义于 Rectangle 结构体上的 area 方法,如示例 5-13 所示: + +```rust +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +impl Rectangle { + fn area(&self) -> u32 { + self.width * self.height + } +} + +fn main() { + let rect1 = Rectangle { + width: 30, + height: 50, + }; + + println!( + "The area of the rectangle is {} square pixels.", + rect1.area() + ); +} +``` +为了使函数定义于 Rectangle 的上下文中,我们开始了一个 impl 块(impl 是 implementation 的缩写),这个 impl 块中的所有内容都将与 Rectangle 类型相关联。接着将 area 函数移动到 impl 大括号中,并将签名中的第一个(在这里也是唯一一个)参数和函数体中其他地方的对应参数改成 self。然后在 main 中将我们先前调用 area 方法并传递 rect1 作为参数的地方,改成使用方法语法(method syntax)在 Rectangle 实例上调用 area 方法。方法语法获取一个实例并加上一个点号,后跟方法名、圆括号以及任何参数。 + + +* &self 的理由跟在函数版本中使用 &Rectangle 是相同的:我们并不想获取所有权,只希望能够读取结构体中的数据,而不是写入。 +* 如果想要在方法中改变调用方法的实例,需要将第一个参数改为 &mut self。通过仅仅使用 self 作为第一个参数来使方法获取实例的所有权是很少见的; + + +使用方法替代函数,除了可使用方法语法和不需要在每个函数签名中重复 self 的类型之外,其主要好处在于组织性。我们将某个类型实例能做的所有事情都一起放入 impl 块中,而不是让将来的用户在我们的库中到处寻找 Rectangle 的功能。 + + + + diff --git a/Rust/01 Rust核心语法/04 函数.md b/Rust/01 Rust核心语法/04 函数.md new file mode 100644 index 00000000..cb996c14 --- /dev/null +++ b/Rust/01 Rust核心语法/04 函数.md @@ -0,0 +1,55 @@ +## 函数定义 + + +### 函数定义 +Rust 代码中的函数和变量名使用下划线命名法(snake case,直译为蛇形命名法)规范风格。在下划线命名法中,所有字母都是小写并使用下划线分隔单词。这是一个包含函数定义示例的程序: + +```rust +fn main() { + println!("Hello, world!"); + + another_function(); +} + +fn another_function() { + println!("Another function."); +} +``` + +### 函数参数 + +函数也可以被定义为拥有参数(parameter),参数是特殊变量,是函数签名的一部分。当函数拥有参数(形参)时,可以为这些参数提供具体的值(实参)。技术上讲,这些具体值被称为实参(argument),但是在日常交流中,人们倾向于不区分使用 parameter 和 argument 来表示函数定义中的变量或调用函数时传入的具体值。 + +```rust +fn main() { + another_function(5); +} + +fn another_function(x: i32) { + println!("The value of x is: {}", x); +} +``` + +### 语句和表达式 + +函数体由一系列语句组成,也可选择以表达式结尾。 + +语句(statement)是执行一些操作但不返回值的指令。表达式(expression)计算并产生一个值。 + +语句并不返回值,表达式会计算出一个值。语句 let y = 6; 中的 6 是一个表达式,它计算出的值是 6。函数调用是一个表达式。宏调用是一个表达式。我们用来创建新作用域的大括号(代码块) {} 也是一个表达式 + +列子 + +```rust +fn five() -> i32 { + 5 +} + +fn main() { + let x = five(); + + println!("The value of x is: {}", x); +} +``` +代码块像是一个没有名称的函数,允许有代码块的返回值。函数更像是一个有名称和参数的代码块,也允许有返回值。 + diff --git a/Rust/01 Rust核心语法/05 面向对象.md b/Rust/01 Rust核心语法/05 面向对象.md new file mode 100644 index 00000000..e69de29b diff --git a/Rust/01 Rust核心语法/06 异常处理.md b/Rust/01 Rust核心语法/06 异常处理.md new file mode 100644 index 00000000..e69de29b diff --git a/Rust/01 Rust核心语法/07 模块化.md b/Rust/01 Rust核心语法/07 模块化.md new file mode 100644 index 00000000..e69de29b diff --git a/Rust/01 Rust核心语法/11 所有权和move语法.md b/Rust/01 Rust核心语法/11 所有权和move语法.md new file mode 100644 index 00000000..12a568e7 --- /dev/null +++ b/Rust/01 Rust核心语法/11 所有权和move语法.md @@ -0,0 +1,376 @@ +## 所有权 + +### 基本规则 +* Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。 +* 值在任一时刻有且只有一个所有者。 +* 当所有者(变量)离开作用域,这个值将被丢弃。 + +### 变量作用域 + +变量 s 绑定到了一个字符串字面量,这个字符串值是硬编码进程序代码中的。该变量从声明的那一刻开始直到当前 作用域 结束时都是有效的。 +* 当 s 进入作用域 时,它就是有效的。 +* 这一直持续到它 离开作用域 为止。 +```rust + { // s 在这里无效, 它尚未声明 + let s = "hello"; // 从此处起,s 开始有效 + + // 使用 s + } // 此作用域已结束,s 不再有效 +``` + +### 内存分配 + +这是一个将 String 需要的内存返回给分配器的很自然的位置:当 s 离开作用域的时候。当变量离开作用域,Rust 为我们调用一个特殊的函数。这个函数叫做 drop,在这里 String 的作者可以放置释放内存的代码。Rust 在结尾的 } 处自动调用 drop。 + +```rust + { + let s = String::from("hello"); // 从此处起,s 开始有效 + + // 使用 s + } // 此作用域已结束, + // s 不再有效 +``` + + +### 堆上的数据:移动 + +```rust + let s1 = String::from("hello"); + let s2 = s1; +``` +在 let s2 = s1 之后,Rust 认为 s1 不再有效,因此 Rust 不需要在 s1 离开作用域后清理任何东西。 +Rust 永远也不会自动创建数据的 “深拷贝”。因此,任何 自动 的复制可以被认为对运行时性能影响较小 + + +### 克隆 +我们 确实 需要深度复制 String 中堆上的数据,而不仅仅是栈上的数据,可以使用一个叫做 clone 的通用函数。 +```rust + let s1 = String::from("hello"); + let s2 = s1.clone(); + + println!("s1 = {}, s2 = {}", s1, s2); +``` +当出现 clone 调用时,你知道一些特定的代码被执行而且这些代码可能相当消耗资源。 + +### 只在栈上的数据:克隆 + +```rust + let x = 5; + let y = x; + + println!("x = {}, y = {}", x, y); +``` +### 所有权与函数 +将值传递给函数在语义上与给变量赋值相似。向函数传递值可能会移动或者复制,就像赋值语句一样。 + +```rust +fn main() { + let s = String::from("hello"); // s 进入作用域 + + takes_ownership(s); // s 的值移动到函数里 ... + // ... 所以到这里不再有效 + + let x = 5; // x 进入作用域 + + makes_copy(x); // x 应该移动函数里, + // 但 i32 是 Copy 的,所以在后面可继续使用 x + +} // 这里, x 先移出了作用域,然后是 s。但因为 s 的值已被移走, + // 所以不会有特殊操作 + +fn takes_ownership(some_string: String) { // some_string 进入作用域 + println!("{}", some_string); +} // 这里,some_string 移出作用域并调用 `drop` 方法。占用的内存被释放 + +fn makes_copy(some_integer: i32) { // some_integer 进入作用域 + println!("{}", some_integer); +} // 这里,some_integer 移出作用域。不会有特殊操作 +``` + +### 返回值与所有权 + +```rust +fn main() { + let s1 = gives_ownership(); // gives_ownership 将返回值 + // 移给 s1 + + let s2 = String::from("hello"); // s2 进入作用域 + + let s3 = takes_and_gives_back(s2); // s2 被移动到 + // takes_and_gives_back 中, + // 它也将返回值移给 s3 +} // 这里, s3 移出作用域并被丢弃。s2 也移出作用域,但已被移走, + // 所以什么也不会发生。s1 移出作用域并被丢弃 + +fn gives_ownership() -> String { // gives_ownership 将返回值移动给 + // 调用它的函数 + + let some_string = String::from("yours"); // some_string 进入作用域 + + some_string // 返回 some_string 并移出给调用的函数 +} + +// takes_and_gives_back 将传入字符串并返回该值 +fn takes_and_gives_back(a_string: String) -> String { // a_string 进入作用域 + + a_string // 返回 a_string 并移出给调用的函数 +} +``` + +变量的所有权总是遵循相同的模式:将值赋给另一个变量时移动它。当持有堆中数据值的变量离开作用域时,其值将通过 drop 被清理掉,除非数据被移动为另一个变量所有。 + + + + +## 引用 +### 基本规则 +* 在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用。 +* 引用必须总是有效的。 +### 引用定义 +& 符号就是 引用,它们允许你使用值但不获取其所有权。 + + 借用(borrowing)创建一个引用的行为. + +https://rustwiki.org/zh-CN/book/img/trpl04-05.svg + +```rust +fn main() { + let s1 = String::from("hello"); + + let len = calculate_length(&s1); + + println!("The length of '{}' is {}.", s1, len); +} + +fn calculate_length(s: &String) -> usize { + s.len() +} +``` +变量 s 有效的作用域与函数参数的作用域一样,不过当引用停止使用时并不丢弃它指向的数据,因为我们没有所有权。当函数使用引用而不是实际值作为参数,无需返回值来交还所有权,因为就不曾拥有所有权。 + +引用默认是不可变的。 + +### 可变引用 + +```rust +fn main() { + let mut s = String::from("hello"); + + change(&mut s); +} + +fn change(some_string: &mut String) { + some_string.push_str(", world"); +} +``` +将 s 改为 mut。然后必须在调用 change 函数的地方创建一个可变引用 &mut s,并更新函数签名以接受一个可变引用 some_string: &mut String。这就非常清楚地表明,change 函数将改变它所借用的值。 + +**规则一:** 在同一时间,只能有一个对某一特定数据的可变引用。尝试创建两个可变引用的代码将会失败。 + +```rust + let mut s = String::from("hello"); + + let r1 = &mut s; + let r2 = &mut s; + + println!("{}, {}", r1, r2); +``` +防止同一时间对同一数据进行多个可变引用的限制允许可变性,不过是以一种受限制的方式允许。新 Rustacean 们经常难以适应这一点,因为大部分语言中变量任何时候都是可变的。 + +这个限制的好处是 Rust 可以在编译时就避免数据竞争。数据竞争(data race)类似于竞态条件,它由这三个行为造成: + +1. 两个或更多指针同时访问同一数据。 +2. 至少有一个指针被用来写入数据。 +3. 没有同步数据访问的机制。 + + + +可以使用大括号来创建一个新的作用域,以允许拥有多个可变引用,只是不能 同时 拥有: + +```rust + let mut s = String::from("hello"); + + { + let r1 = &mut s; + } // r1 在这里离开了作用域,所以我们完全可以创建一个新的引用 + + let r2 = &mut s; + +``` +**规则二:** 不能在拥有不可变引用的同时拥有可变引用。使用者可不希望不可变引用的值在他们的眼皮底下突然被改变了!然而,多个不可变引用是可以的,因为没有哪个只能读取数据的人有能力影响其他人读取到的数据。 +* 读写和写写互斥存在 +* 读读不互斥。 + +**规则三:** 引用的作用域从声明的地方开始一直持续到最后一次使用为止。例如,因为最后一次使用不可变引用(println!),发生在声明可变引用之前,所以如下代码是可以编译的: + +```rust +fn main() { + let mut s = String::from("hello"); + + let r1 = &s; // 没问题 + let r2 = &s; // 没问题 + println!("{} and {}", r1, r2); + // 此位置之后 r1 和 r2 不再使用 + + let r3 = &mut s; // 没问题 + println!("{}", r3); +} + +``` + +### 悬垂引用 +在具有指针的语言中,很容易通过释放内存时保留指向它的指针而错误地生成一个 悬垂指针(dangling pointer),所谓悬垂指针是其指向的内存可能已经被分配给其它持有者。相比之下,在 Rust 中编译器确保引用永远也不会变成悬垂状态:当你拥有一些数据的引用,编译器确保数据不会在其引用之前离开作用域。 + +让我们尝试创建一个悬垂引用,Rust 会通过一个编译时错误来避免: + +```rust +fn main() { + let reference_to_nothing = dangle(); +} + +fn dangle() -> &String { + let s = String::from("hello"); + + &s +} + +``` + + +在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用。 +引用必须总是有效的。 + + +## 切片与引用 +### 切片的使用 + + +```rust +fn first_word(s: &String) -> &str { + let bytes = s.as_bytes(); + + for (i, &item) in bytes.iter().enumerate() { + if item == b' ' { + return &s[0..i]; + } + } + + &s[..] +} +``` +* 当调用 first_word 时,会返回与底层数据关联的单个值。这个值由一个 slice 开始位置的引用和 slice 中元素的数量组成。 +* slice与String的声明周期相同 + +### 切片的作用 + + +对于 Rust 的 .. range 语法,如果想要从索引 0 开始,可以不写两个点号之前的值。换句话说,如下两个语句是相同的: +```rust + +#![allow(unused)] +fn main() { +let s = String::from("hello"); + +let slice = &s[0..2]; +let slice = &s[..2]; +} + +``` + +依此类推,如果 slice 包含 String 的最后一个字节,也可以舍弃尾部的数字。这意味着如下也是相同的: +```rust + +#![allow(unused)] +fn main() { +let s = String::from("hello"); + +let len = s.len(); + +let slice = &s[3..len]; +let slice = &s[3..]; +} + +``` + +也可以同时舍弃这两个值来获取整个字符串的 slice。所以如下亦是相同的: + +```rust + +#![allow(unused)] +fn main() { +let s = String::from("hello"); + +let len = s.len(); + +let slice = &s[0..len]; +let slice = &s[..]; +} + +``` + +### 实例 +一下代码编译会报错 +```rust +fn main() { + let mut s = String::from("hello world"); + + let word = first_word(&s); + + s.clear(); // error! + + println!("the first word is: {}", word); +} +``` + +```rust +$ cargo run + Compiling ownership v0.1.0 (file:///projects/ownership) +error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable + --> src/main.rs:18:5 + | +16 | let word = first_word(&s); + | -- immutable borrow occurs here +17 | +18 | s.clear(); // error! + | ^^^^^^^^^ mutable borrow occurs here +19 | +20 | println!("the first word is: {}", word); + | ---- immutable borrow later used here + +For more information about this error, try `rustc --explain E0502`. +error: could not compile `ownership` due to previous error + +``` + +回忆一下借用规则,当拥有某值的不可变引用时,就不能再获取一个可变引用。因为 clear 需要清空 String,它尝试获取一个可变引用。在调用 clear 之后的 println! 使用了 word 中的引用,所以这个不可变的引用在此时必须仍然有效。Rust 不允许 clear 中的可变引用和 word 中的不可变引用同时存在,因此编译失败。Rust 不仅使得我们的 API 简单易用,也在编译时就消除了一整类的错误! + +### 解释 + +* 字符串字面量就是 slice。这里 s 的类型是 &str:它是一个指向二进制程序特定位置的 slice。这也就是为什么字符串字面量是不可变的;&str 是一个不可变引用。 +```rust + +#![allow(unused)] +fn main() { +let s = "Hello, world!"; +} + +``` + +### 其他slice同理 + +字符串 slice,正如你想象的那样,是针对字符串的。不过也有更通用的 slice 类型。考虑一下这个数组: + +```rust +let a = [1, 2, 3, 4, 5]; + +``` + + +就跟我们想要获取字符串的一部分那样,我们也会想要引用数组的一部分。我们可以这样做: + +```rust +let a = [1, 2, 3, 4, 5]; +let slice = &a[1..3]; +``` + +这个 slice 的类型是 &[i32]。它跟字符串 slice 的工作方式一样,通过存储第一个集合元素的引用和一个集合总长度。你可以对其他所有集合使用这类 slice。 \ No newline at end of file diff --git a/Rust/01 Rust核心语法/12 Cargo包管理和构建.md b/Rust/01 Rust核心语法/12 Cargo包管理和构建.md new file mode 100644 index 00000000..e69de29b diff --git a/Rust/01 Rust核心语法/image/2025-08-21T02:34:52.388Z.png b/Rust/01 Rust核心语法/image/2025-08-21T02:34:52.388Z.png new file mode 100644 index 00000000..32ef1d0d Binary files /dev/null and b/Rust/01 Rust核心语法/image/2025-08-21T02:34:52.388Z.png differ diff --git a/Rust/面试说明.md b/Rust/面试说明.md new file mode 100644 index 00000000..055db682 --- /dev/null +++ b/Rust/面试说明.md @@ -0,0 +1,15 @@ +评测 + +如何评测效果。有哪些指标,性能提升也要有指标,用哪些业务负载。要具体到用什么负载、用什么指标衡量,这个指标为什么能衡量,评测方案是如何设计的。 + +不要说你认为好的指标,而是经过筛选的最能反应负载的指标。 + + +如何跟调度器集成 + +list watch的实现方案 + +代码没看原理应该清楚可以讲一讲。 + + + diff --git a/kubenets/面试/01 创建Pod会经过哪些步骤.md b/kubenets/面试/01 创建Pod会经过哪些步骤.md new file mode 100644 index 00000000..71061e87 --- /dev/null +++ b/kubenets/面试/01 创建Pod会经过哪些步骤.md @@ -0,0 +1,79 @@ +在 Kubernetes(简称 K8s)集群中,直接执行 `kubectl apply -f pod.yaml` 来部署一个 Pod 时,会触发集群的一系列自动化流程。这是一个典型的声明式操作,用户只需描述 Pod 的期望状态(通过 YAML 文件),K8s 控制平面和节点组件会协同工作,将其转化为实际运行状态。整个过程体现了 K8s 的核心原理:声明式 API、期望状态驱动(Desired State vs. Actual State)、组件间松耦合协作(通过 API Server 和 etcd 实现状态同步),以及自愈机制(如重试和健康检查)。下面,我结合 K8s 原理,从请求提交到 Pod 运行就绪,逐阶段详细拆解整个流程。 + +### 阶段 1:用户请求提交与 API Server 处理 +用户通过 `kubectl apply` 命令提交 Pod 的 YAML 配置(包含 metadata 如名称、命名空间;spec 如容器镜像、资源需求、端口等)。`kubectl` 会解析 YAML,确保它符合 K8s 的 Pod 资源规范(v1 Pod API),然后转换为 JSON 格式的 HTTP 请求发送到 K8s API Server。这体现了 K8s 的 RESTful API 设计,所有资源操作(如创建、更新)都通过 API Server 统一入口。 + +- **认证与授权**: + - API Server 首先进行认证(Authentication):验证请求者的身份,使用 kubeconfig 中的证书、Bearer Token 或其他机制(如 Service Account)。如果认证失败,请求将被拒绝(返回 401 Unauthorized)。 + - 接着是授权(Authorization):基于 Role-Based Access Control (RBAC) 检查用户是否有权限在指定命名空间创建 Pod(需要 `pods/create` 权限)。如果没有权限,返回 403 Forbidden。这确保了集群的安全性和多租户隔离。 + +- **准入控制(Admission Control)**: + - 通过认证授权后,API Server 调用一组准入控制器(Admission Controllers),这些是可插拔的 webhook 或内置插件,用于在资源持久化前校验和修改配置。 + - **校验(Validating)**:检查 Pod spec 的合法性,例如容器镜像是否有效、资源请求(如 CPU/Memory)是否为正值、端口是否冲突等。如果违反规范(如使用无效的镜像标签),请求将被拒绝。 + - **修改(Mutating)**:自动填充默认值,例如如果未指定 `restartPolicy`,默认为 `Always`;或添加默认的 SecurityContext(如非 root 用户运行)。 + - **高级准入**:如果集群启用了 PodSecurityAdmission(PSA)或旧的 PodSecurityPolicy (PSP),会强制安全约束,如禁止特权容器或主机路径挂载。这体现了 K8s 的安全第一原理,防止恶意或不安全的配置进入集群。 + +- **持久化到 etcd**: + - 所有准入通过后,API Server 将 Pod 对象(包括 metadata、spec 和初始 status 为 Pending)写入 etcd(K8s 的分布式键值存储,集群的单一真相来源)。同时生成 `metadata.resourceVersion` 用于乐观并发控制(避免并发修改冲突)。etcd 的 Watch 机制会通知其他组件(如 Scheduler)这个新 Pod 的存在。这一步标志着 Pod 被 “创建”,但还未调度或运行。 + +如果 YAML 中已存在同名 Pod,`apply` 会计算差异(基于 strategic merge patch),仅更新变更部分,而非覆盖整个对象。这体现了声明式的幂等性:多次 apply 相同的 YAML 不会导致意外行为。 + +### 阶段 2:Scheduler 调度 Pod 到目标节点 +Pod 写入 etcd 后,Scheduler(调度器,一个独立的控制平面组件)通过 Watch API Server 感知到这个未调度 Pod(`spec.nodeName` 为空),启动调度循环。Scheduler 的核心原理是谓词(Predicate)和优先级(Priority)机制,确保 Pod 被分配到最合适的节点,实现资源利用最大化和高可用。 + +- **筛选候选节点(Filter/Predicate)**: + - 从集群所有节点(通过 Node 对象列表)中过滤出可行节点。规则包括: + - **资源匹配**:检查节点剩余资源(从 Node status.allocatable 减去已分配)是否满足 Pod 的 `spec.resources.requests` 和 `limits`。例如,如果 Pod 请求 2Gi 内存,节点剩余不足则排除。 + - **亲和性与反亲和性**:Pod 的 `nodeAffinity` 或 `podAffinity` 要求节点/其他 Pod 的标签匹配(如 `nodeSelector: {env: prod}`),否则排除。 + - **污点与容忍(Taints & Tolerations)**:节点可能有 Taint(如 `NoSchedule`),Pod 必须声明 `tolerations` 来容忍,否则无法调度。 + - **其他约束**:如卷亲和性(Pod 的 PV 必须在节点可用)、主机端口(`hostPort`)是否已被占用、节点状态(Ready)等。如果无节点匹配,Pod 保持 Pending,事件日志会记录原因(如 "0/5 nodes are available: 2 Insufficient cpu")。 + +- **节点打分(Score/Priority)**: + - 对过滤后的节点,按优先级函数打分(0-10 分,乘以权重后总分 0-100)。默认函数包括: + - **资源均衡**:LeastRequestedPriority(优先低负载节点)和 BalancedResourceAllocation(均衡 CPU/内存使用)。 + - **亲和性加分**:如 Pod 与现有 Pod 在同一拓扑域(zone/rack)加分,提高容灾或降低延迟。 + - **自定义扩展**:集群可配置插件或 extender webhook 来添加规则(如优先 SSD 节点)。 + - 选择最高分节点,如果平分则随机选一。 + +- **绑定节点(Bind)**: + - Scheduler 通过 API Server 更新 Pod 对象:设置 `spec.nodeName` 为目标节点,并添加绑定事件。更新写入 etcd,Pod status 变为 Scheduled。这体现了异步协作:Scheduler 不直接操作节点,而是通过 etcd 通知 Kubelet。 + +如果集群节点不足或约束太严,调度可能失败,Pod 无限 Pending,用户需通过 `kubectl describe pod` 查看事件。 + +### 阶段 3:目标节点的 Kubelet 创建并运行 Pod +节点上的 Kubelet(每个节点运行的代理组件)通过 Watch 机制发现分配给自己的 Pod(匹配 `spec.nodeName`),开始本地执行。Kubelet 的原理是调和循环(Reconcile Loop):不断比较 Pod 的期望状态与实际状态,并采取行动实现一致性。 + +- **PodSpec 解析与准备**: + - Kubelet 从 API Server 获取完整 Pod 配置,进行本地校验(如确认节点资源足够)。如果不符,会报告事件并拒绝。 + +- **容器运行时交互(CRI)**: + - Kubelet 通过 Container Runtime Interface (CRI) 与底层运行时(如 Docker、containerd)通信: + - **镜像拉取**:根据 `spec.containers[*].image` 从仓库拉取镜像(使用 ImagePullSecrets 如果需要认证)。如果失败(如网络问题),状态变为 ImagePullBackOff,重试指数退避。 + - **卷准备**:创建并挂载 volumes,如 EmptyDir(临时目录)、ConfigMap/Secret(注入配置)、PersistentVolume (PV)(通过 CSI 驱动绑定持久存储)。 + - **网络配置**:调用 Container Network Interface (CNI) 插件(如 Flannel、Calico)分配 Pod IP,设置 veth 接口和路由,确保 Pod 网络连通(符合 K8s 的网络模型:所有 Pod 可互相访问,无 NAT)。 + +- **启动容器**: + - 先运行 `initContainers`(顺序执行初始化,如数据准备),成功后启动主容器。 + - 应用 `securityContext`(如 runAsUser、capabilities),注入环境变量(envFrom)、命令(command/args)。 + - 如果 `hostNetwork: true`,Pod 共享节点网络命名空间。 + +- **健康检查与状态报告**: + - **探针(Probes)**:执行 Startup/Liveness/Readiness Probe(如 exec、httpGet、tcpSocket)。Liveness 失败则重启容器(根据 `restartPolicy`:Always/OnFailure/Never);Readiness 失败则从 Service Endpoints 移除 Pod IP。 + - Kubelet 每 10 秒(默认)同步 Pod status 到 API Server(写入 etcd),包括条件如 PodScheduled、ContainersReady。用户看到 status 从 Pending -> ContainerCreating -> Running。 + +如果容器崩溃,Kubelet 自愈:重启并记录日志(`kubectl logs` 查看)。 + +### 阶段 4:网络与服务就绪(Kube-proxy 参与) +Pod Running 后,如果有匹配的 Service(通过 labels selector),Kube-proxy(节点组件)Watch 到 Pod IP 变化,更新本地转发规则: +- 使用 iptables 或 IPVS 将 Service 的 ClusterIP(VIP)流量负载均衡到 Pod IP:Port。 +- 如果是 NodePort/LoadBalancer,配置外部访问。 + +这实现了服务发现和负载均衡的解耦:Pod 可动态变化,Service 提供稳定入口。 + +### 特殊情况与自愈 +- **失败处理**:如镜像不存在(ErrImagePull)、资源不足(FailedScheduling),K8s 会记录事件并重试。CrashLoopBackOff 表示反复崩溃,需用户干预。 +- **更新与删除**:后续 apply 修改 YAML,会触发类似流程,但仅更新差异(RollingUpdate 如果是多副本,但单 Pod 无此)。 +- **观测性**:所有步骤生成事件(`kubectl get events`),日志和指标(通过 Metrics Server)便于调试。 + +### 总结:K8s 核心原理体现 +直接 apply Pod YAML 体现了 K8s 的声明式范式:用户声明期望,系统自动调和实际状态。通过 API Server 的中心化、etcd 的持久化和组件的 Watch/Informers 机制,确保分布式一致性。这比 imperative 命令(如 docker run)更具可扩展性和可靠性,支持大规模自动化运维。如果 Pod 是 Deployment/ReplicaSet 的一部分,流程类似但 Controller Manager 会介入管理副本。实际操作中,推荐使用更高层抽象(如 Deployment)而非裸 Pod,以获得内置滚动更新和自愈。 \ No newline at end of file diff --git a/kubenets/面试/02 调度器如何工作.md b/kubenets/面试/02 调度器如何工作.md new file mode 100644 index 00000000..e69de29b