mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-08-01 16:28:03 +08:00
Compare commits
11 Commits
33f3c2c52e
...
2d3bf00753
Author | SHA1 | Date | |
---|---|---|---|
|
2d3bf00753 | ||
|
be124ce75f | ||
|
61e5c720e1 | ||
|
2a994b4120 | ||
|
58326aeb41 | ||
|
45c170a4d8 | ||
|
ef5cf4b8f5 | ||
|
090becd595 | ||
|
4f28b59057 | ||
|
617c5ba139 | ||
|
761bb0e101 |
@ -41,7 +41,7 @@ title: JavaGuide(Java学习&面试指南)
|
||||
|
||||
- [Java 集合常见知识点&面试题总结(上)](./java/collection/java-collection-questions-01.md) (必看 :+1:)
|
||||
- [Java 集合常见知识点&面试题总结(下)](./java/collection/java-collection-questions-02.md) (必看 :+1:)
|
||||
- [Java 容器使用注意事项总结](./java/collection/java-collection-precautions-for-use.md)
|
||||
- [Java 集合使用注意事项总结](./java/collection/java-collection-precautions-for-use.md)
|
||||
|
||||
**源码分析**:
|
||||
|
||||
|
@ -18,7 +18,7 @@ head:
|
||||
|
||||
### Java 语言有哪些特点?
|
||||
|
||||
1. 简单易学;
|
||||
1. 简单易学(语法简单,上手容易);
|
||||
2. 面向对象(封装,继承,多态);
|
||||
3. 平台无关性( Java 虚拟机实现平台无关性);
|
||||
4. 支持多线程( C++ 语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而 Java 语言却提供了多线程支持);
|
||||
|
@ -190,7 +190,7 @@ System.out.println(listOfStrings);
|
||||
|
||||
- 头部插入/删除:只需要修改头结点的指针即可完成插入/删除操作,因此时间复杂度为 O(1)。
|
||||
- 尾部插入/删除:只需要修改尾结点的指针即可完成插入/删除操作,因此时间复杂度为 O(1)。
|
||||
- 指定位置插入/删除:需要先移动到指定位置,再修改指定节点的指针完成插入/删除,因此需要移动平均 n/2 个元素,时间复杂度为 O(n)。
|
||||
- 指定位置插入/删除:需要先移动到指定位置,再修改指定节点的指针完成插入/删除,因此需要遍历平均 n/2 个元素,时间复杂度为 O(n)。
|
||||
|
||||
这里简单列举一个例子:假如我们要删除节点 9 的话,需要先遍历链表找到该节点。然后,再执行相应节点指针指向的更改,具体的源码可以参考:[LinkedList 源码分析](./linkedlist-source-code.md) 。
|
||||
|
||||
|
@ -464,7 +464,7 @@ JDK1.8 默认使用的是 Parallel Scavenge + Parallel Old,如果指定了-XX:
|
||||
- **无法处理浮动垃圾;**
|
||||
- **它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生。**
|
||||
|
||||
**从 JDK9 开始,CMS 收集器已被弃用。**
|
||||
**CMS垃圾回收器在Java 9中已经被标记为过时(deprecated),并在Java 14中被移除。**
|
||||
|
||||
### G1 收集器
|
||||
|
||||
|
@ -145,7 +145,7 @@ JVM 具有四种类型的 GC 实现:
|
||||
```bash
|
||||
-XX:+UseSerialGC
|
||||
-XX:+UseParallelGC
|
||||
-XX:+UseParNewGC
|
||||
-XX:+UseConcMarkSweepGC
|
||||
-XX:+UseG1GC
|
||||
```
|
||||
|
||||
|
@ -125,7 +125,25 @@ Java 堆是垃圾收集器管理的主要区域,因此也被称作 **GC 堆(
|
||||
|
||||
**JDK 8 版本之后 PermGen(永久代) 已被 Metaspace(元空间) 取代,元空间使用的是本地内存。** (我会在方法区这部分内容详细介绍到)。
|
||||
|
||||
大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 S0 或者 S1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 `-XX:MaxTenuringThreshold` 来设置。
|
||||
大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 S0 或者 S1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 `-XX:MaxTenuringThreshold` 来设置。不过,设置的值应该在 0-15,否则会爆出以下错误:
|
||||
|
||||
```bash
|
||||
MaxTenuringThreshold of 20 is invalid; must be between 0 and 15
|
||||
```
|
||||
|
||||
**为什么年龄只能是 0-15? **
|
||||
|
||||
因为记录年龄的区域在对象头中,这个区域的大小通常是 4 位。这 4 位可以表示的最大二进制数字是 1111,即十进制的 15。因此,对象的年龄被限制为 0 到 15。
|
||||
|
||||
这里我们简单结合对象布局来详细介绍一下。
|
||||
|
||||
在 HotSpot 虚拟机中,对象在内存中存储的布局可以分为 3 块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。其中,对象头包括两部分:标记字段(Mark Word)和类型指针(Klass Word)。关于对象内存布局的详细介绍,后文会介绍到,这里就不重复提了。
|
||||
|
||||
这个年龄信息就是在标记字段中存放的(标记字段还存放了对象自身的其他信息比如哈希码、锁状态信息等等)。`markOop.hpp`定义了标记字(mark word)的结构:
|
||||
|
||||

|
||||
|
||||
可以看到对象年龄占用的大小确实是 4 位。
|
||||
|
||||
> **🐛 修正(参见:[issue552](https://github.com/Snailclimb/JavaGuide/issues/552))**:“Hotspot 遍历所有对象时,按照年龄从小到大对其所占用的大小进行累加,当累加到某个年龄时,所累加的大小超过了 Survivor 区的一半,则取这个年龄和 `MaxTenuringThreshold` 中更小的一个值,作为新的晋升年龄阈值”。
|
||||
>
|
||||
@ -134,7 +152,7 @@ Java 堆是垃圾收集器管理的主要区域,因此也被称作 **GC 堆(
|
||||
> ```c++
|
||||
> uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
|
||||
> //survivor_capacity是survivor空间的大小
|
||||
> size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
|
||||
> size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);//TargetSurvivorRatio 为50
|
||||
> size_t total = 0;
|
||||
> uint age = 1;
|
||||
> while (age < table_size) {
|
||||
@ -314,9 +332,12 @@ Java 对象的创建过程我建议最好是能默写出来,并且要掌握每
|
||||
|
||||
### 对象的内存布局
|
||||
|
||||
在 Hotspot 虚拟机中,对象在内存中的布局可以分为 3 块区域:**对象头**、**实例数据**和**对齐填充**。
|
||||
在 Hotspot 虚拟机中,对象在内存中的布局可以分为 3 块区域:**对象头(Header)**、**实例数据(Instance Data)**和**对齐填充(Padding)**。
|
||||
|
||||
**Hotspot 虚拟机的对象头包括两部分信息**,**第一部分用于存储对象自身的运行时数据**(哈希码、GC 分代年龄、锁状态标志等等),**另一部分是类型指针**,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
|
||||
对象头包括两部分信息:
|
||||
|
||||
1. 标记字段(Mark Word):用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等等。
|
||||
2. 类型指针(Klass Word):对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
|
||||
|
||||
**实例数据部分是对象真正存储的有效信息**,也是在程序中所定义的各种类型的字段内容。
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user