Java Source File compile 之后生成 .Class文件(字节码文件), .Class文件 Interpret 之后生成 机器码被电脑使用
1. 线程
虚拟机线程:保持JVM位于安全点 (包括 stop-the-word 垃圾回收,线程栈dump,线程暂停,线程偏向锁解除 (biased lock release))
周期性任务线程:负责定时器Event (就是JVM Interrupt)
GC线程:负责 Garbage Collection
编译器线程:负责 Java 中 compiler 的活动
信号分发线程:接收发送到JVM的signal并且调度jvm thread 处理
2. JVM 内存区域
Thread Local 线程私有 (User kernal 用户内核态):
- pc 程序计数器
- JVM Stack 虚拟机栈 (JAVA 方法的出栈入栈)
- Native Method Stack 本地方法栈 (Java Native Method 的出栈入栈; 都是非java语言的方法)
Thread Shared 线程共享 (JVM kernal JVM 内核态):
- Heap 堆 (Java对象和数组都存放在这,GC发生的地方)
- Method Area 方法区 (也是永久代,所有constant, static variables; Constant Pool 常量池也在这里)
Direct Memory 直接内存 (Java 整体内存):
- Meta Data Space 元数据区/元空间 (原来永久代的元空间在java8移到了直接内存中) (GC 垃圾回收不能发生在 Direct Memory)
3. JVM 运行时内存
Young:
- Eden: New Object 存放的位置
- Survivor From: 上一次Minor GC留下的内容
- Survivor To: 这一次Minor GC发生的地方
Old:
又称为 Tenured 永久代
Minor GC:
- 清理 Young (当JVM不能给new object 分配内存空间时会触发 Minor GC)
- 过程又分为--复制,清空和互换
- 复制: 将 Eden 和 Survivor From 中的内容复制到 Survivor To, 准备 Minor GC
- 清空: 清空 Eden 和 Survivor From 中的内容
- 互换: 将 Survivor To 中的内容 和 Survivor From 中的内容互换, 即将Minor GC 结果存入 Survivor From
Major GC:
- 清理 Old (一般 执行 Major GC 都伴随着一次 Minor GC 的完成)
- 过程使用 标记清除算法 (mark-sweep)
Full GC: Minor GC + Major GC
4. 常用GC算法
确定 Gabage 的方法
- Reference Counting 引用计数法 (如果 Object 的 Reference-Counting =0;那么这个Object 不会被用到,即可回收)
- GC Roots 可达性分析 (如果 GC-Roots 到达不了Object, 证明Object 不可达; 再经过2次标记过程,即可回收)
Gabage Collection 方法
- Mark-Sweep 标记清除 --- 标记不用的内存块并清除 (缺点: 内存碎片化严重)
- Copying 复制 --- 将整个内存一分为二,先用一半,内存满了之后吧还在使用的内存复制到另一半上 (缺点: 效率不高)
- *Mark-Compact 标记整理 --- 标记不用的内存然后把仍然需要使用的内存块移到内存的一侧上,让内存不再碎片化
- *Generational Collection 分代收集 --- 将内存分为 Young 和 Old 并进行分代收集
- Young 区收集 (使用 Copying,因为每次要回收大量Object, 所以用 Copying效率更高) (使用Copying实现minorGC流程)
- Old 区收集 (使用 Mark-Compact,因为每次要回收少量Object,所以用Mark-Compact效率更高)(用Mark-Compact实现MajorGC流程)
5. Java 中的四种引用类型(强引用, 软引用, 弱引用, 虚引用)-- 在 引用计数法中使用
// 强引用
String strongReference = new String("abc");
// 软引用
String str = new String("abc");
SoftReference<String> softReference = new SoftReference<String>(str);
// 弱引用
WeakReference<String> weakReference = new WeakReference<>(str);
// 弱引用转强引用
String strongReference = weakReference.get();
// 创建虚引用,要求必须与一个引用队列关联
ReferenceQueue queue = new ReferenceQueue();
PhantomReference pr = new PhantomReference(str, queue);
6. GC分代收集 对比 分区收集
GC分代收集:在 Young 中使用 Copying, 在 Old 中使用 Mark-Sweep 或者 Mark-Compact
分区收集:把整个Heap分为很多小空间,每个小空间独立使用,独立GC;减少GC产生的停顿
7. GC垃圾收集器
- Serial 垃圾收集器 (单线程 + Copying算法) :运行时需要暂停其他工作Thread
- ParNew 垃圾收集器 (多线程 + Serial收集器):运行时也需要暂停其他工作Thread
- Parallel Scavenge 垃圾收集器 (多线程 + Copying算法):focus on Program的高吞吐量;有自适应调节策略
- Serial Old 垃圾收集器 (单线程 + Mark-Compact)(Serial 老年代版本):运行时需要暂停其他工作Thread
- Parallel Old 垃圾收集器 (多线程 + Mark-Compact)(Parallel Scavenge 老年代版本):高吞吐量;有自适应调节策略
- CMS 垃圾收集器 (多线程 + Mark-Sweep):全称:Concureent Mark-Sweep,有最短的GC停顿时间;流程如下
初始标记:暂停所有工作Thread,Mark所有GC Roots标记到的Objects
并发标记:不暂停工作Thread,与工作Thread同时进行 GC Roots
重新标记:并发标记会有误差,关闭所有工作Thread进行重新标记
并发清除:不暂停工作Thread,与工作Thread同时进行 清除 GC Roots 不可达Objects
7. G1 垃圾收集器 : 优点:基于Mark-Compact不产生内存碎片;低GC停顿时间;因为是分区域GC所以效率最高
8. JAVA IO/NIO
- 字节流 (InputStream, OutputStream);字符流 (Read, Write)
1. Java 多线程I/O模型
- Blocked I/O 阻塞 I/O 模型: 用 阻塞的方式实现多线程
- Non-Blocked I/O 非阻塞 I/O 模型:不阻塞的方式实现多线程,需要一直询问kernel是否ready, CPU占用高
- 多路复用 I/O 模型:NIO使用多个User Thread去询问kernel,而多路复用 I/O 只使用一个 User Thread
- 信号驱动 I/O 模型:kernel 向 User Thread 发送一个信号,让 User Thread 进行 Read/Write
- Async I/O 异步 I/O 模型:异步使用,最高效
2. Java NIO (I/O 是面向 Stream 的,NIO 是面向 Buffer 的)
- Channel --- I/O中的InputStream,OutputStream 是单向的,FileChannel, DatagramChannel, SocketChannel 等
- Buffer --- NIO 中的缓存数组, ByteBuffer, IntBuffer, CharBuffer, LongBuffer, DoubleBuffer, FloatBuffer 等
- JavaJatu--- 监听 NIO 的 Channel 上是否发生 Event, 如果发生则进行响应处理
9. JVM 类加载机制
- 加载: 将 机器码加载变成 Java Class 也就是 Java 类
- 验证: 验证生成的Java 类是否正确是否可用
- 准备: 给 Java 类中的 static variables 分配内存, 分配默认值
- 解析:把 Constant Pool 中的 符号引用全部换成直接引用
- 符号引用:就是没有指针指向Heap 中的 Object
- 直接引用: 有指针指向 Heap 中的 Object
5. 初始化: 给 Java 类中的 static variables 分配初始值
不会执行 类初始化的情况:
- 当 Java 类 中存在父子类,只有 父类会初始化,子类不会初始化
- Array Object 不会初始化
- Class.forName 反射可以设置不初始化
10. JVM 类加载器
- BootStrap ClassLoader:加载 JAVA_HOME/lib 中的类
- Extension ClassLoader:加载 JAVA_HOME/lib.ext 中的类
- Application ClassLoader:加载 ClassPath 即用户路径中的类
- 双亲委派:当子类要进行类加载,会请求父类先加载,如果父类无法加载完成,子类才自己加载
- OSGI 动态模型系统 (Open Service Gateway Initiative): 让 Java 项目模块化