@@ -786,7 +786,7 @@ public class MethodDemo {
786786* 如果第 1 个阶段中没有找到适配的方法,那么在允许自动装拆箱,但不允许可变长参数的情况下选取重载方法
787787* 如果第 2 个阶段中没有找到适配的方法,那么在允许自动装拆箱以及可变长参数的情况下选取重载方法
788788
789- 如果 Java 编译器在同一个阶段中找到了多个适配的方法,那么会选择一个最为贴切的,而决定贴切程度的一个关键就是形式参数类型的继承关系,一般会选择形参为参数类型的子类的方法,因为子类时更具体的实现:
789+ 如果 Java 编译器在同一个阶段中找到了多个适配的方法,那么会选择一个最为贴切的,而决定贴切程度的一个关键就是形式参数类型的继承关系,** 一般会选择形参为参数类型的子类的方法,因为子类时更具体的实现** :
790790
791791```java
792792public class MethodDemo {
@@ -4318,19 +4318,19 @@ TreeSet 集合自排序的方式:
431843182. 字符串类型的元素会按照首字符的编号排序
431943193. 对于自定义的引用数据类型,TreeSet 默认无法排序,执行的时候报错,因为不知道排序规则
43204320
4321- 自定义的引用数据类型,TreeSet 默认无法排序,需要定制排序的规则,方案有2种 :
4321+ 自定义的引用数据类型,TreeSet 默认无法排序,需要定制排序的规则,方案有 2 种 :
43224322
43234323 * 直接为**对象的类**实现比较器规则接口 Comparable,重写比较方法:
43244324
4325- 方法:`public int compareTo(Employee o): this是比较者, o是被比较者 `
4325+ 方法:`public int compareTo(Employee o): this 是比较者, o 是被比较者 `
43264326
4327- * 比较者大于被比较者,返回正数
4327+ * 比较者大于被比较者,返回正数(升序)
43284328 * 比较者小于被比较者,返回负数
43294329 * 比较者等于被比较者,返回 0
43304330
43314331 * 直接为**集合**设置比较器 Comparator 对象,重写比较方法:
43324332
4333- 方法:`public int compare(Employee o1, Employee o2): o1比较者, o2被比较者 `
4333+ 方法:`public int compare(Employee o1, Employee o2): o1 比较者, o2 被比较者 `
43344334
43354335 * 比较者大于被比较者,返回正数
43364336 * 比较者小于被比较者,返回负数
@@ -8443,12 +8443,16 @@ public class AnnotationDemo01 {
84438443
84448444
84458445
8446+ ***
8447+
8448+
8449+
84468450#### 特殊属性
84478451
84488452注解的特殊属性名称:value
84498453
8450- * 如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
8451- * 如果有多个属性,且多个属性没有默认值,那么value是不能省略的
8454+ * 如果只有一个 value 属性的情况下,使用 value 属性的时候可以省略 value 名称不写
8455+ * 如果有多个属性,且多个属性没有默认值,那么 value 是不能省略的
84528456
84538457```java
84548458//@Book("/deleteBook.action")
@@ -8470,7 +8474,7 @@ public class AnnotationDemo01{
84708474
84718475### 元注解
84728476
8473- 元注解是sun公司提供的 ,用来注解自定义注解
8477+ 元注解是 sun 公司提供的 ,用来注解自定义注解
84748478
84758479元注解有四个:
84768480
@@ -11107,7 +11111,7 @@ Serial GC、Parallel GC、Concurrent Mark Sweep GC 这三个 GC 不同:
1110711111
1110811112##### 静态集合
1110911113
11110- 静态集合类的生命周期与JVM程序一致 ,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。原因是长生命周期的对象持有短生命周期对象的引用 ,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收
11114+ 静态集合类的生命周期与 JVM 程序一致 ,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。原因是**长生命周期的对象持有短生命周期对象的引用** ,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收
1111111115
1111211116```java
1111311117public class MemoryLeak {
@@ -11184,7 +11188,7 @@ public class UsingRandom {
1118411188
1118511189##### 改变哈希
1118611190
11187- 当一个对象被存储进 HashSet 集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段 ,否则对象修改后的哈希值与最初存储进 HashSet 集合中时的哈希值不同,这种情况下使用该对象的当前引用作为的参数去 HashSet 集合中检索对象返回 false,导致无法从 HashSet 集合中单独删除当前对象,造成内存泄漏
11191+ 当一个对象被存储进 HashSet 集合中以后,就**不能修改这个对象中的那些参与计算哈希值的字段** ,否则对象修改后的哈希值与最初存储进 HashSet 集合中时的哈希值不同,这种情况下使用该对象的当前引用作为的参数去 HashSet 集合中检索对象返回 false,导致无法从 HashSet 集合中单独删除当前对象,造成内存泄漏
1118811192
1118911193
1119011194
@@ -11280,14 +11284,14 @@ public Object pop() {
1128011284
1128111285* 普通对象:分为两部分
1128211286
11283- * Mark Word:用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等
11287+ * ** Mark Word** :用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等
1128411288
1128511289 ```ruby
1128611290 hash(25) + age(4) + lock(3) = 32bit #32位系统
1128711291 unused(25+1) + hash(31) + age(4) + lock(3) = 64bit #64位系统
1128811292 ```
1128911293
11290- * Klass Word:类型指针,对象指向它的类的元数据的指针 ,虚拟机通过这个指针来确定这个对象是哪个类的实例;在64位系统中,开启指针压缩(-XX:+UseCompressedOops)或者 JVM 堆的最大值小于 32G,这个指针也是 4byte,否则是 8byte(就是 Java 中的一个引用的大小)
11294+ * ** Klass Word** :类型指针,指向该对象的类的元数据的指针 ,虚拟机通过这个指针来确定这个对象是哪个类的实例;在64位系统中,开启指针压缩(-XX:+UseCompressedOops)或者 JVM 堆的最大值小于 32G,这个指针也是 4byte,否则是 8byte(就是 Java 中的一个引用的大小)
1129111295
1129211296 ```ruby
1129311297 |-----------------------------------------------------|
@@ -11309,7 +11313,7 @@ public Object pop() {
1130911313
1131011314实例数据:实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的,都需要记录起来
1131111315
11312- 对齐填充:Padding 起占位符的作用。64 位系统,由于 HotSpot VM 的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,就是对象的大小必须是 8 字节的整数倍,而对象头部分正好是 8 字节的倍数(1倍或者2倍),因此当对象实例数据部分没有对齐时,就需要通过对齐填充来补全
11316+ 对齐填充:Padding 起占位符的作用。64 位系统,由于 HotSpot VM 的自动内存管理系统要求**对象起始地址必须是 8 字节的整数倍** ,就是对象的大小必须是 8 字节的整数倍,而对象头部分正好是 8 字节的倍数(1倍或者2倍),因此当对象实例数据部分没有对齐时,就需要通过对齐填充来补全
1131311317
113141131832位系统:
1131511319
@@ -11339,7 +11343,7 @@ public Object pop() {
1133911343
1134011344#### 实际大小
1134111345
11342- 浅堆(Shallow Heap):对象本身占用的内存,不包括内部引用对象的大小,32 位系统中一个**对象引用占 4 个字节**,每个对象头占用 8 个字节,根据堆快照格式不同,对象的大小会同 8 字节进行对齐
11346+ 浅堆(Shallow Heap):** 对象本身占用的内存,不包括内部引用对象的大小** ,32 位系统中一个**对象引用占 4 个字节**,每个对象头占用 8 个字节,根据堆快照格式不同,对象的大小会同 8 字节进行对齐
1134311347
1134411348JDK7 中的 String:2个 int 值共占 8 字节,value 对象引用占用 4 字节,对象头 8 字节,对齐后占 24 字节,为 String 对象的浅堆大小,与 value 实际取值无关,无论字符串长度如何,浅堆大小始终是 24 字节
1134511349
@@ -11410,14 +11414,14 @@ private int hash32;
1141011414
1141111415JVM 是通过栈帧中的对象引用访问到其内部的对象实例:
1141211416
11413- * 句柄访问
11414- 使用该方式,Java 堆中会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息
11417+ * 句柄访问:Java 堆中会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息
11418+
1141511419 优点:reference 中存储的是稳定的句柄地址,在对象被移动(垃圾收集)时只会改变句柄中的实例数据指针,而 reference 本身不需要被修改。
1141611420
1141711421 <img src="https://gitee.com/seazean/images/raw/master/Java/JVM-对象访问-句柄访问.png" style="zoom: 50%;" />
1141811422
11419- * 直接指针(HotSpot采用)
11420- 使用该方式,Java 堆对象的布局必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址
11423+ * 直接指针(HotSpot采用):Java 堆对象的布局必须考虑如何放置访问类型数据的相关信息,reference 中直接存储的对象地址
11424+
1142111425 优点:速度更快,**节省了一次指针定位的时间开销**
1142211426
1142311427 <img src="https://gitee.com/seazean/images/raw/master/Java/JVM-对象访问-直接指针.png" style="zoom: 67%;" />
@@ -11439,7 +11443,7 @@ JVM 是通过栈帧中的对象引用访问到其内部的对象实例:
11439114431. 创建阶段 (Created):
11440114442. 应用阶段 (In Use):对象至少被一个强引用持有着
11441114453. 不可见阶段 (Invisible):程序的执行已经超出了该对象的作用域,不再持有该对象的任何强引用
11442- 4. 不可达阶段 (Unreachable):该对象不再被任何强引用所持有,包括GC Root的强引用
11446+ 4. 不可达阶段 (Unreachable):该对象不再被任何强引用所持有,包括 GC Root 的强引用
11443114475. 收集阶段 (Collected):垃圾回收器已经对该对象的内存空间重新分配做好准备,该对象如果重写了finalize()方法,则会去执行该方法
11444114486. 终结阶段 (Finalized):等待垃圾回收器对该对象空间进行回收,当对象执行完finalize()方法后仍然处于不可达状态时进入该阶段
11445114497. 对象空间重分配阶段 (De-allocated):垃圾回收器对该对象的所占用的内存空间进行回收或者再分配
@@ -11458,7 +11462,7 @@ JVM 是通过栈帧中的对象引用访问到其内部的对象实例:
1145811462
1145911463类在第一次实例化加载一次,后续实例化不再加载,引用第一次加载的类
1146011464
11461- Java对象创建时机 :
11465+ Java 对象创建时机 :
1146211466
11463114671. 使用 new 关键字创建对象:由执行类实例创建表达式而引起的对象创建
1146411468
@@ -11508,17 +11512,17 @@ Java对象创建时机:
1150811512
11509115134. 初始化分配的空间:虚拟机将分配到的内存空间都初始化为零值(不包括对象头),保证对象实例字段在不赋值时可以直接使用,程序能访问到这些字段的数据类型所对应的零值
1151011514
11511- 5. 设置对象的对象头:将对象的所属类(类的元数据信息)、对象的HashCode、对象的GC信息、锁信息等数据存储在对象的对象头中
11515+ 5. 设置对象的对象头:将对象的所属类(类的元数据信息)、对象的 HashCode、对象的 GC 信息、锁信息等数据存储在对象头中
1151211516
11513- 6. 执行init方法进行实例化 :实例变量初始化、实例代码块初始化 、构造函数初始化
11517+ 6. 执行 init 方法进行实例化 :实例变量初始化、实例代码块初始化 、构造函数初始化
1151411518
1151511519 * 实例变量初始化与实例代码块初始化:
1151611520
11517- 对实例变量直接赋值或者使用实例代码块赋值,编译器会将其中的代码放到类的构造函数中去,并且这些代码会被放在对超类构造函数的调用语句之后 (**Java要求构造函数的第一条语句必须是超类构造函数的调用语句 **),构造函数本身的代码之前
11521+ 对实例变量直接赋值或者使用实例代码块赋值,编译器会将其中的代码放到类的构造函数中去,并且这些代码会被放在对超类构造函数的调用语句之后 (**Java 要求构造函数的第一条语句必须是超类构造函数的调用语句 **),构造函数本身的代码之前
1151811522
1151911523 * 构造函数初始化:
1152011524
11521- **Java要求在实例化类之前 ,必须先实例化其超类,以保证所创建实例的完整性**,在准备实例化一个类的对象前,首先准备实例化该类的父类,如果该类的父类还有父类,那么准备实例化该类的父类的父类,依次递归直到递归到Object类。然后从Object类依次对以下各类进行实例化 ,初始化父类中的变量和执行构造函数
11525+ **Java 要求在实例化类之前 ,必须先实例化其超类,以保证所创建实例的完整性**,在准备实例化一个类的对象前,首先准备实例化该类的父类,如果该类的父类还有父类,那么准备实例化该类的父类的父类,依次递归直到递归到 Object 类。然后从 Object 类依次对以下各类进行实例化 ,初始化父类中的变量和执行构造函数
1152211526
1152311527
1152411528
@@ -18697,7 +18701,7 @@ private static final class ProxyClassFactory {
1869718701
1869818702#### CGLIB
1869918703
18700- CGLIB 是一个功能强大,高性能的代码生成包,为没有实现接口的类提供代理,为 JDK 动态代理提供了补充
18704+ CGLIB 是一个功能强大,高性能的代码生成包,为没有实现接口的类提供代理,为 JDK 动态代理提供了补充($$Proxy)
1870118705
1870218706* CGLIB 是第三方提供的包,所以需要引入 jar 包的坐标:
1870318707
0 commit comments