一.JVM 虚拟机
使用 Java 语言编写.java
Source Code 文件,通过 javac 编译成.class
Byte Code 文件,JVM 就可以识别.class
文件,并使用 JIT compiler 将.class
文件编译为机器码后运行。
class loader 类加载器
:将所需的类加载到内存,必要时将类实例化成实例。
图中中间部分是进程的内存逻辑结构,称为 Jvm 运行时区域,由下面几部分构成:
Method Area
方法区:所有线程共享的内存空间,存放已加载的类信息、常量和静态变量。
Heap
堆:所有线程共享的内存空间,存放创建的所有对象。堆是靠 GC 垃圾回收器管理的。
Java Stack
栈:每个线程会分配一个栈,存放线程用的本地变量、方法参数和返回值等。
PC 寄存器
:PC, 即 Program Counter,每一个线程用于记录当前线程正在执行的字节码
指令地址。因为线程需要切换,当一个线程被切换回来需要执行的时候,知道执行到哪里了。
本地方法栈
:为本地方法执行构建的内存空间,存放本地方法执行时的局部变量、操作数等。
所谓本地方法,简单的说是非 Java 实现的方法,例如操作系统的 C 编写的库提供的本地
方法,Java 调用这些本地方法接口执行。但是要注意,本地方法应该避免直接编程使用,
因为 Java 可能跨平台使用,如果用了 Windows API,换到了 Linux 平台部署就有了问题。
二.内存垃圾回收
2.2 GC 内存垃圾回收器
堆内存里面经常创建、销毁对象,内存高频率的被使用、被释放。如果不妥善处理,一个
使用频繁的进程,将可能有内存空间,但是无法分配出可用内存空间,因为没有连续地址
的内存区域了,内存全是碎片化的数据。因此,JVM 的 GC 即是用来解决这样的问题的。
2.2.1 GC 内存回收基本算法
1. 引用计数
每一个堆内对象上都与一个私有引用计数器,记录着被引用的次数,引用计数清零,该对象
所占用堆内存就可以被回收。循环引用的对象都无法引用计数归零,就无法清除。
2. 标记-清除 Mark-Sweep
顾名思义,标记和清除垃圾收集器有两个阶段
- 标记阶段
标记阶段,找到所有可访问对象打个标记。需要注意的是,在标记阶段,会停止应用程序
线程,以避免在标记阶段对对象状态进行更改。
- 清除阶段
清理阶段,遍历整个堆,对未标记对象清理。在清除阶段,所有来自标记阶段的未标记对
象将从内存中删除,从而释放空间。
从上面的图中可以看出,在清除阶段之后可能存在大量的可用内存区域。但是,由于这些