Skip to content

Commit

Permalink
docs: update 01-jvm-memory-structure.md (doocs#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeMinty authored May 10, 2022
1 parent 88b1981 commit f5d121c
Showing 1 changed file with 10 additions and 11 deletions.
21 changes: 10 additions & 11 deletions docs/01-jvm-memory-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ Java 虚拟机栈的栈顶的栈帧是当前正在执行的活动栈,也就是
- 静态链接:当一个字节码文件被装载进 JVM 内部时,如果被调用的目标方法在编译期可知,且运行时期间保持不变,这种情况下降调用方的符号引用转为直接引用的过程称为静态链接。
- 动态链接:如果被调用的方法无法再编译期被确定下来,只能在运行期将调用的方法的符号引用转为直接引用,这种引用转换过程具备动态性,因此被称为动态链接。
- 方法绑定
- 早期绑定:被调用的目标方法如果再编译期可知,且运行期保持不变。
- 早期绑定:被调用的目标方法如果在编译期可知,且运行期保持不变。
- 晚期绑定:被调用的方法在编译期无法被确定,只能够在程序运行期根据实际的类型绑定相关的方法。
- 非虚方法:如果方法在编译期就确定了具体的调用版本,则这个版本在运行时是不可变的。这样的方法称为非虚方法静态方法,私有方法,final 方法,实例构造器,父类方法都是非虚方法,除了这些以外都是虚方法。
- 非虚方法:如果方法在编译期就确定了具体的调用版本,则这个版本在运行时是不可变的。这样的方法称为非虚方法静态方法,私有方法,final 方法,实例构造器,父类方法都是非虚方法除了这些以外都是虚方法。
- 虚方法表:面向对象的编程中,会很频繁的使用动态分配,如果每次动态分配的过程都要重新在类的方法元数据中搜索合适的目标的话,就可能影响到执行效率,因此为了提高性能,JVM 采用在类的方法区建立一个虚方法表,使用索引表来代替查找。
- 每个类都有一个虚方法表,表中存放着各个方法的实际入口。
- 虚方法表会在类加载的链接阶段被创建,并开始初始化,类的变量初始值准备完成之后,JVM 会把该类的方法也初始化完毕。
Expand All @@ -97,7 +97,7 @@ Java 中任何一个普通方法都具备虚函数的特征(运行期确认,

### Java 虚拟机栈的特点

- 运行速度特别快,仅仅次于 PC 寄存器。
- 运行速度特别快仅仅次于 PC 寄存器。
- 局部变量表随着栈帧的创建而创建,它的大小在编译时确定,创建时只需分配事先规定的大小即可。在方法运行过程中,局部变量表的大小不会发生改变。
- Java 虚拟机栈会出现两种异常:StackOverFlowError 和 OutOfMemoryError。
- StackOverFlowError 若 Java 虚拟机栈的大小不允许动态扩展,那么当线程请求栈的深度超过当前 Java 虚拟机栈的最大深度时,抛出 StackOverFlowError 异常。
Expand Down Expand Up @@ -173,7 +173,7 @@ Java 中任何一个普通方法都具备虚函数的特征(运行期确认,

### Full GC /Major GC 触发条件

- 显示调用`System.gc()`,老年代的空间不够,方法区的空间不够等都会触发 Full GC,同时对新生代和老年代回收,FUll GC 的 STW 的时间最长,应该要避免
- 显示调用`System.gc()`老年代的空间不够方法区的空间不够等都会触发 Full GC,同时对新生代和老年代回收,FUll GC 的 STW 的时间最长,应该要避免
- 在出现 Major GC 之前,会先触发 Minor GC,如果老年代的空间还是不够就会触发 Major GC,STW 的时间长于 Minor GC

### 逃逸分析
Expand Down Expand Up @@ -224,17 +224,16 @@ s 是一个方法内部变量,上边的代码中直接将 s 返回,这个 St

### TLAB

- TLAB 的全称是 Thread Local Allocation Buffer,即线程本地分配缓存区,是属于 Eden 区的,这是一个线程专用的内存分配区域,线程私有,默认开启的(当然也不是绝对的,也要看哪种类型的虚拟机)

- 堆是全局共享的, 在同一时间,可能会有多个线程在堆上申请空间,但每次的对象分配需要同步的进行(虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性)但是效率却有点下降
- TLAB 的全称是 Thread Local Allocation Buffer,即线程本地分配缓存区,是属于 Eden 区的,这是一个线程专用的内存分配区域,线程私有,默认开启的(当然也不是绝对的,也要看哪种类型的虚拟机)
- 堆是全局共享的,在同一时间,可能会有多个线程在堆上申请空间,但每次的对象分配需要同步的进行(虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性)但是效率却有点下降
- 所以用 TLAB 来避免多线程冲突,在给对象分配内存时,每个线程使用自己的 TLAB,这样可以使得线程同步,提高了对象分配的效率
- 当然并不是所有的对象都可以在 TLAB 中分配内存成功,如果失败了就会使用加锁的机制来保持操作的原子性
- `-XX:+UseTLAB `使用 TLAB,`-XX:+TLABSize` 设置 TLAB 大小
- `-XX:+UseTLAB `使用 TLAB`-XX:+TLABSize` 设置 TLAB 大小

### 四种引用方式

- 强引用:创建一个对象并把这个对象赋给一个引用变量 , 普通 new 出来对象的变量引用都是强引用,有引用变量指向时永远不会被垃圾回收,jvm 即使抛出 OOM,可以将引用赋值为 null,那么它所指向的对象就会被垃圾回收
- 软引用:如果一个对象具有软引用,内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用
- 强引用:创建一个对象并把这个对象赋给一个引用变量普通 new 出来对象的变量引用都是强引用,有引用变量指向时永远不会被垃圾回收,jvm 即使抛出 OOM,可以将引用赋值为 null,那么它所指向的对象就会被垃圾回收
- 软引用:如果一个对象具有软引用,内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用
- 弱引用:非必需对象,当 JVM 进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。
- 虚引用:虚引用并不会决定对象的生命周期,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

Expand Down Expand Up @@ -275,7 +274,7 @@ Java 虚拟机规范中定义方法区是堆的一个逻辑部分。方法区存
### 直接内存与堆内存比较

- 直接内存申请空间耗费更高的性能
- 直接内存读取 IO 的性能要优于普通的堆内存
- 直接内存读取 IO 的性能要优于普通的堆内存
- 直接内存作用链: 本地 IO -> 直接内存 -> 本地 IO
- 堆内存作用链:本地 IO -> 直接内存 -> 非直接内存 -> 直接内存 -> 本地 IO

Expand Down

0 comments on commit f5d121c

Please sign in to comment.